Reputation: 167
If I have understood correctly, tuples in elixir are represented with {}
while Maps are represented as a key:value pair with %{key: value}
.
In the following code, the Stream.filter
and Enum.map
accepts entries
as input, which is a Map
and iterates over it.
But the lambda
function inside them is doing a pattern matching on {_, entry}
which is a tuple
. How come this works?
defmodule TodoList do
defstruct auto_id: 1, entries: %{}
def new(), do: %TodoList{}
def add_entry(todo_list, entry) do
entry = Map.put(entry, :id, todo_list.auto_id)
new_entries = Map.put(
todo_list.entries,
todo_list.auto_id,
entry)
%TodoList{todo_list |
entries: new_entries,
auto_id: todo_list.auto_id + 1
}
end
def entries(todo_list, date) do
todo_list.entries
|> Stream.filter(fn {_, entry} -> entry.date == date end)
|> Enum.map(fn {_, entry} -> entry end)
end
end
Upvotes: 1
Views: 355
Reputation: 121000
Iterations in Elixir are possible by the implementation of Enumerable
protocol. That means, anything, implementing Enumerable
can be iterated using methods from Enum
and String
modules.
The implementation of this protocol for Map
delegates to Enumerable.List.reduce/3
, passing the map converted to a list with :maps.to_list/1
.
The latter transforms the map to a list in the form [{k1, v1}, {k2, v2}, ...]
.
iex|1 ▶ :maps.to_list(%{k1: :v1, k2: :v2})
#⇒ [k1: :v1, k2: :v2] # essentially the list of tuples
iex|2 ▶ [k1: :v1, k2: :v2] == [{:k1, :v1}, {:k2, :v2}]
#⇒ true
These tuples are being emitted in Enum.map
in your example.
Upvotes: 8