Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the equal sign within a function parameter in Elixir?

Tags:

elixir

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.

like image 269
Tsutomu Avatar asked Jan 31 '17 13:01

Tsutomu


2 Answers

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.

like image 118
Justin Wood Avatar answered Oct 24 '22 21:10

Justin Wood


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.

like image 27
Tsutomu Avatar answered Oct 24 '22 20:10

Tsutomu