Comprehensions in Elixir have the following syntax:
for <generator(s) or filter(s), separated by commas> [, into: <value>], do: <expression>
For example:
iex> for x <- [1, 2, 3], do: x * x
[1,4,9]
Generators such as
x
are named local variables you can use in theexpression
argument.Note that variable assignments such as
x
in comprehensions are local in scope, so it doesn’t affect variables with the same name in the outer scope.
We can have multiple generators x
and y
:
iex> for x <- [1, 2, 3], y <- [4,5,6], do: x * y
[4, 5, 6, 8, 10, 12, 12, 15, 18]
We can use filters alongside generators. When the condition in the filter evaluates to false, that particular iteration is skipped.
iex> for x <- [1, 2, 3], y < 5, y <- [4,5,6], do: x * y
[4, 8, 12]
Unlike guard clauses, you can call your own module’s methods within filter.
The into
parameter takes in a collection for storing the comprehension’s results:
iex> for item <- [:bananas, :milk],
quantity <- [5, 2],
into: Map.new,
do: {item, quantity}
{bananas: 2, milk: 2}
We can also use pattern matching in comprehensions:
iex> prices = [ bananas: 1.80, milk: 4.00 ] # keyword list
iex> cart = [
[id: 1, name: :bananas],
[id: 2, name: :milk],
[id: 3, name: :bananas],
[id: 4, name: :yoghurt]
] # list of keyword lists
iex(20)> for item <- cart,
{_, item_name} <- item, # generator
(item_name in Keyword.keys prices), # filter
{name, price} <- prices, # generator
item_name == name, # filter
do: price
[1.8, 4.0, 1.8]