defmodule Foo do
defstruct [:foo]
end
%{foo: "foo"} = %Foo{foo: "foo"} # Works
foo = %{foo: "foo"}
^foo = %Foo{foo: "foo"} # Fails with "** (MatchError) no match of right hand side value: %Foo{foo: "foo"}"
Is this expected?
The doc says:
iex> ^x = 2
Because we have pinned x
when it was bound to the value of 1
, it is equivalent to the following:
iex> 1 = 2
I guess this is not the same thing when a map is on the left side.
It is the same thing, but you’re mixing up values and patterns. ^
is not a pattern substitution operator. It binds a value inside a pattern and always checks for exact equality. It happens in the case of simple integers that the value 1
and the pattern 1
are equal. In case of lists however [1 | rest]
is a valid pattern but if you had:
iex(1)> rest = [2,3]
[2, 3]
iex(2)> list = [1 | rest]
[1, 2, 3]
iex(3)> ^list = [1,2,3,4]
** (MatchError) no match of right hand side value: [1, 2, 3, 4]
iex(3)> [1 | rest] = [1,2,3,4]
[1, 2, 3, 4]
The same thing happens with maps as you observe. When you do ^foo =
it’s going to check that foo
is exactly equal to the relevant part of the right hand side, it isn’t going to convert foo
's value into a pattern.
5 Likes
OK, I understand, thank you.
I thought I could use ^
to “reuse” a pattern like this:
^pattern = value
^pattern = other_value
...