I have defined a Foo
module like this:
defmodule Foo do
def hello(x = %{name: name}) do
IO.inspect [x, name]
end
end
If I run the Foo.hello(%{name: "Alice"})
, I get the following result:
[%{name: "Alice"}, "Alice"]
Then, I learned that I can rewrite the Foo
module without changing its functionality like this:
defmodule Foo do
def hello(%{name: name} = x) do
IO.inspect [x, name]
end
end
Why this is possible? What is the equal sign within a function parameter? Is it a normal match operator?
In my understanding, the operator =
matches the value on the right side against the pattern on the left side.
[Edit]
After reading Justin's answer, I posted an answer by myself. But, I still need help.
I want to know whether the =
operator does behave differently within the function head and why.
And I want to find an official documentation if available.
It is indeed still the match operator.
The reason you can do this is the same reason you can match like this
iex(1)> 1 = x
** (CompileError) iex:3: undefined function x/0
iex(2)> x = 1
1
iex(3)> 1 = x
1
Inside your function head, x
has a value as soon as you use the function and pass an argument into it (same reason you can define the function as def hello(x) do ... end
). Which means you are allowed to use it on the right hand side of the match operator.
After googling for a while, I found an explanation on http://learnyousomeerlang.com/syntax-in-functions.
This article refers an Erlang fuction:
valid_time({Date = {Y,M,D}, Time = {H,Min,S}}) ->
io:format("The Date tuple (~p) says today is: ~p/~p/~p,~n",[Date,Y,M,D]),
io:format("The time tuple (~p) indicates: ~p:~p:~p.~n", [Time,H,Min,S]);
Then it says:
Note that it is possible to use the
=
operator in the function head, allowing us to match both the content inside a tuple ({Y,M,D}
) and the tuple as a whole (Date
).
It is about Erlang, but It seems the mechanism is the same on Elixir.
For experiment, I rewrote the Foo
module as follows:
defmodule Foo do
def hello(%{name: x} = %{name: y}) do
IO.inspect [x, y]
end
end
Then I ran the Foo.hello(%{name: "Alice"})
, and got this:
["Alice", "Alice"]
The pattern matching on the argument is done against two patterns on both sides of the =
operator.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With