Reputation: 7805
I'm reading the great Joy of Elixir and I'm trying to wrap my head around the order of operations in the pattern matching example.
I've got the list
crew = [
%{name: "mal", age: 40},
%{name: "zoey", age: 36},
]
Now I can use pattern matching to take the first element of the list, and assign the name to a different variable like
[first = %{name: first_name} | others] = crew
I understand that the first element in crew
was assigned to first
and that the name
of first
was assigned to first_name
:
iex> first
%{age: 40, name: "mal"}
iex> first_name
"mal"
According to the examples I can also assign the name to another variable from right-to-left:
%{name: first_name2} = first
But the same fails when I try it from left-to-right:
iex> first = %{name: first_name3}
** (CompileError) iex:33: undefined function first_name3/0
(stdlib) lists.erl:1354: :lists.mapfoldl/3
(stdlib) lists.erl:1355: :lists.mapfoldl/3
My question is: Why is left-to-right assignment OK within list matching, but fails outside of list matching?
Upvotes: 2
Views: 528
Reputation: 1629
The right side of =
(match operator) is evaluated first. In the expression
first = %{name: first_name3}
It tries to get the value of first_name3
, but there's no first_name3
in the scope.
For the expression
[first = %{name: first_name} | others] = crew
you can think of it as
[first = %{name: first_name} = %{age: 40, name: "mal"} | others] = crew
or
others = tl(crew)
head = hd(crew)
first = %{name: first_name} = head
Here's another example:
x = "foo"
binds the variable x
to string "foo"
(because x
is unbound at first). Now that x
has been bound
to "foo"
, "foo" = x
is also a valid expression since "foo"
matches x
.
Upvotes: 2
Reputation: 827
This is because the way elixir evaluates a sequence. When you start up your iex your environment will be empty. When you type in first = %{name: first_name3} It will start by evaluating the right hand side. Inside of the actual map you are trying to associate the key "name" to the variable first_name3. If first_name3 does not exist in your environment the expression will fail to evaluate and you will get the undefined function error.
this should work:
first_name3 = "John"
first = %{name: first_name3}
Upvotes: 1