with and for
with Keyword
with chains a sequence of pattern matches. It succeeds when every
step matches and gives you back the value of the last expression. If
any step fails, with falls through to the else block (or returns
the value that did not match).
Here is the smallest possible example:
iex> with {:ok, n} <- {:ok, 42} do
...> "got #{n}"
...> end
"got 42"
The ← operator reads as "pattern match against". It is very close
to =, but when the match fails, with stops instead of raising.
A more realistic example chains two lookups that both have to succeed:
iex> user = %{name: "Alice", city: "Berlin"}
iex> with {:ok, name} <- Map.fetch(user, :name),
...> {:ok, city} <- Map.fetch(user, :city) do
...> "#{name} lives in #{city}"
...> else
...> :error -> "missing data"
...> end
"Alice lives in Berlin"
If either Map.fetch/2 returns :error, the else branch runs.
The ← arrow uses
pattern matching,
so every shape you can write on the left side of = also works here.
|
for Comprehensions
for comprehensions iterate over one or more enumerables (lists,
maps, ranges) and build a new collection from the results.
Here is the smallest example:
iex> for num <- [1, 2, 3, 4, 5], do: num * num
[1, 4, 9, 16, 25]
for walks each number in the list, squares it, and collects the
results into a new list.
You can add a filter expression after the generator. Elements for
which the filter returns false are skipped:
iex> for num <- [1, 2, 3, 4, 5], rem(num, 2) == 1, do: num * num
[1, 9, 25]
Only odd numbers survive the filter, so the result contains their squares.
For most transformations a function from the
Enum module reads more naturally than a
for comprehension. Reach for for when you want to combine several
generators or filters in one place.
|