Understand the pin “^" operator in Elixir
To understand what the ^
operator does in Elixir, you have to understand what =
does.
Pattern matching
In most languages, =
is the assignment operator. If you want to assign the value 1
to a variable a
, depending on the language, you are going to write something like a = 1
. The value of the right hand side is assigned to the value of the left hand side.
But in Elixir, =
isn’t the assignment operator. it is the match operator. The match operator is at the heart of one of the most powerful feature of the elixir language: pattern matching.
Here is what pattern matching does :
- it matches the value on the left hand side with the value on the right hand side.
- if it matches and if the left hand side includes a variable, it assigns the corresponding value from the right hand side to the variable.
Therefore if we write a = 1
in elixir, we are matching the left hand side a
to the right hand side 1
. As it matches, elixir assigns the value 1
to a
.
Let ‘s now share an example from the elixir console (see here if you want to install elixir and see how to use the console) :
iex> [x, y, z] = [1, 2, 3]
[1, 2, 3]
iex> x
1
iex> y
2
iex> z
3
Here, elixir matches x
with 1
, y
with 2
and z
with 3
. Each variable on the left hand side has a matching variable on the right hand side.
but if we write:
iex> [x, y, z, t] = [1, 2, 3]
** (MatchError) no match of right hand side value: [1, 2, 3]
There’s nothing that matches on the right hand side with t
, so elixir returns an error.
The pin operator
Now that you understand what pattern matching is, let’s have a look at the pin ( ^
) operator !
remember the two effect of pattern matching :
it matches the value on the left hand side with the value on the right hand side. if it matches and if the left hand side includes a variable, it assigns the corresponding value from the right hand side to the variable.
This is great but sometimes, for some reasons, I just want to make sure what I have on the left hand side matches with what I have on the right hand side, without any assignment in case I have a variable on the left hand side. In other words, I just want to compare both sides.
This is exactly what the ^
operator allows me to do : It pins the variable on its value and prevent any assignment to this variable when using pattern matching.
iex> a = 1
1
iex> ^a = 2
** (MatchError) no match of right hand side value: 2
First we pattern match a
and 1
, so 1
is assigned to a
. Then we pattern match a
with 2
but we pinned a
on its value 1
, so elixir returns an error. ^a = 2
is like if we had 1 = 2
. It does not match.
Let’s use our previous example again:
iex> [x, y, z] = [1, 2, 3]
[1, 2, 3]
iex> x
1
iex> y
2
iex> z
3
iex> [x, ^y , z] = [4, 5, 6]
** (MatchError) no match of right hand side value: [4, 5, 6]
iex> x
1
iex> y
2
iex> z
3
iex> [x, y , z] = [4, 5, 6]
[4, 5, 6]
iex> x
4
iex> y
5
iex> z
6
Here we pin y
on 2, so when we try [x, ^y, z] = [4, 5, 6]
, elixir returns an error because y
is pinned to 2 which does not match 5
. The left hand side and the right hand side do not match and there is no assignment, not even to x
nor z
. It’s like if we had [x, 2, z] = [4, 5, 6]
.
Next we try [x, y, z] = [4, 5, 6]
and this time we do not get any error: y
isn’t pinned, so if there is a matching value on the right hand side, y
will be assigned to it. Here, both sides match so x
returns 4, y
returns 5
, and z
returns 6
.
Now you understand how the ^
operator works ! You should be able to use it in your project if needed. Hope you enjoy your Elixir journey as much as I do !
Thank you to @ cybrok from the Elixir Slack for his feedback that helped me improve this article.