Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is x = x +1 valid in Elixir?

Everything I've read about Elixir says that assignment should be thought of as pattern matching. If so then why does x = x + 1 work in Elixir? There is no value of x for which x = x + 1.

like image 995
iphone007 Avatar asked Feb 23 '19 20:02

iphone007


Video Answer


2 Answers

Everything I've read about Elixir says that assignment should be thought of as pattern matching.

In Elixir, = is called the pattern match operator, but it does not work the same way as the pattern match operator in Erlang. That's because in Elixir variables are not single assignment like they are in Erlang. Here's the way Erlang works:

~/erlang_programs$ erl
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V9.3  (abort with ^G)

1> X = 15.
15

2> X = 100.
** exception error: no match of right hand side value 100

3> X.
15

4> 

Therefore, in Erlang this fails:

4> X = X + 1.
** exception error: no match of right hand side value 16

Things are pretty simple with Erlang's single assignment: because X already has a value, the line X = X + 1 cannot be an attempt to assign a new value to X, so that line is an attempt to pattern match (15 = 15 + 1), which will always fail.

On the other hand, in Elixir variables are not single assignment:

Interactive Elixir (1.6.6) - press Ctrl+C to exit (type h() ENTER for help)

iex(1)> x = 15
15

iex(2)> x = 100
100

iex(3)> x
100

iex(4)> 

The fact that variables are not single assignment in Elixir means that Elixir needs to make a choice when you write:

x = 10
x = x + 1  #or even x = 15

Choice 1) Should the second line be interpreted as assignment to x?
Choice 2) Should the second line be interpreted as an attempt to pattern match (i.e. 10 = 11)?

Elixir goes with Choice 1. That means that actually performing a pattern match with the so called pattern match operator in Elixir is more difficult: you have to use the pin operator(^) in conjunction with the match operator(=):

x = 10
^x = x + 1  

Now, the second line will always fail. There is also a trick that will work in some situations if you want to perform pattern matching without using the pin operator:

x = 10
12 = x

In the second line, you put the variable on the right hand side. I think the rule can be stated like this: On the right hand side of the pattern match operator(=), variables are always evaluated, i.e. replaced with their values. On the left hand side variables are always assigned to--unless the pin operator is used, in which case a pinned variable is replaced by its current value and then pattern matched against the right hand side. As a result, it's probably more accurate to call Elixir's = operator a hybrid assignment/pattern match operator.

like image 160
7stud Avatar answered Nov 15 '22 09:11

7stud


You can imagine x = x + 1 being rewritten by the compiler to something like x2 = x1 + 1.

This is pretty close to how it works. It's not a simple index number like I used here, but the concept is the same. The variables seen by the BEAM are immutable, and there is no rebinding going on at that level.

In Erlang programs, you'll find code like X2 = X1 + 1 all over. There are downsides to both approaches. José Valim made a conscious choice to allow rebinding of variables when he designed Elixir, and he wrote a blog post comparing the two approaches and the different bugs you run the risk of:

http://blog.plataformatec.com.br/2016/01/comparing-elixir-and-erlang-variables/

like image 33
Martin Svalin Avatar answered Nov 15 '22 10:11

Martin Svalin