Skip to content

Instantly share code, notes, and snippets.

@mattsan
Created December 6, 2018 08:04
Show Gist options
  • Save mattsan/9aab272cba94516c59961823c0b3f6ff to your computer and use it in GitHub Desktop.
Save mattsan/9aab272cba94516c59961823c0b3f6ff to your computer and use it in GitHub Desktop.
Elixir の Enumerable プロトコルを利用する検証コード(Range の自作)
defmodule MyRange do
@moduledoc """
自作の Range の実装
詳しくは [Enumerable protocol のドキュメント](https://hexdocs.pm/elixir/Enumerable.html)を参照。
"""
defstruct first: 0, last: 0
def new(first, last) do
%MyRange{first: first, last: last}
end
defimpl Enumerable do
def count(%MyRange{first: first, last: last}), do: {:ok, last - first + 1}
def member?(%MyRange{first: first, last: last}, value), do: {:ok, first <= value && value <= last}
def slice(%MyRange{} = my_range), do: {:ok, Enum.count(my_range), fn first, last -> MyRange.new(first, last) end}
def reduce(_, {:halt, acc}, _), do: {:halted, acc}
def reduce(%MyRange{} = my_range, {:suspend, acc}, fun), do: {:suspended, acc, &reduce(my_range, &1, fun)}
def reduce(%MyRange{first: first, last: last}, {:cont, acc}, _) when first > last, do: {:done, acc}
def reduce(%MyRange{first: first} = my_range, {:cont, acc}, fun), do: reduce(%{my_range | first: first + 1}, fun.(first, acc), fun)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment