Packages

Lazy, external iterators for Elixir.

Current section

Files

Jump to
iterex lib iter iterable map.ex
Raw

lib/iter/iterable/map.ex

defmodule Iter.Iterable.Map do
defstruct iterator: nil, map: nil
@moduledoc """
A wrapper around Erlang's `:maps.iterator`.
"""
alias Iter.{Impl, IntoIterable, Iterable}
@type t :: %__MODULE__{iterator: :maps.iterator(), map: map}
@doc """
Convert a map into a map iterable.
"""
@spec new(map) :: t
def new(map) when is_map(map), do: %__MODULE__{iterator: :maps.iterator(map), map: map}
defimpl Iterable do
use Impl
import :erlang, only: [map_get: 2]
@doc false
@impl true
def next(map_iterable) do
case :maps.next(map_iterable.iterator) do
:none -> :done
{key, value, iterator} -> {:ok, {key, value}, %{map_iterable | iterator: iterator}}
end
end
@doc false
@impl true
def filter(map_iterable, predicate) when is_function(predicate, 1) do
new_map = :maps.filter(&filter_predicate(predicate, &1, &2), map_iterable.iterator)
IntoIterable.into_iterable(new_map)
end
defp filter_predicate(predicate, key, value) do
case predicate.({key, value}) do
true -> true
{true, _} -> true
_ -> false
end
end
@doc false
@impl true
def each(map_iterable, fun) when is_function(fun, 1) do
:maps.foreach(&each_fun(fun, &1, &2), map_iterable.iterator)
:done
end
defp each_fun(fun, key, value), do: fun.({key, value})
@doc false
@impl true
def member?(map, {key, value}) when map_get(key, map.map) == value, do: true
def member?(_, _), do: false
end
defimpl IntoIterable do
@doc false
def into_iterable(self), do: self
end
end