Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the "pin" operator for, and are Elixir variables mutable?

Currently trying to understand the "^" operator in Elixir. From the website:

The pin operator ^ can be used when there is no interest in rebinding a variable but rather in matching against its value prior to the match:

Source - http://elixir-lang.org/getting_started/4.html

With this in mind, you can attach a new value to a symbol like so:

iex> x = 1  # Outputs "1" iex> x = 2  # Outputs "2" 

I can also do:

iex> x = x + 1  # Outputs "3"! 

So my first question is; Are Elixir variables mutable? It sure looks like if that's the case... Shouldn't that be possible in a functional programming language?

So now we come to the "^" operator...

iex> x = 1  # Outputs "1" iex> x = 2  # Outputs "2" iex> x = 1  # Outputs "1" iex> ^x = 2 # "MatchError" iex> ^x = 1  # Outputs "1" 

I think the effect of "^" is to lock "x" to the last value binded to it. Is that all there is to it? Why not just ensure that all 'matches'/assignments are immutable like Erlang itself?

I was just getting used to that...

like image 806
Charlie Avatar asked Jan 15 '15 19:01

Charlie


People also ask

What is pin operator in Elixir?

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.

How do you define a variable in Elixir?

Variable Naming Naming variables follow a snake_case convention in Elixir, i.e., all variables must start with a lowercase letter, followed by 0 or more letters(both upper and lower case), followed at the end by an optional '?' OR '!' .


1 Answers

The data in Elixir is still immutable, but there are couple of shorthands, that let you type less or don't worry about finding new names. In Erlang, you could often see code like this:

SortedList = sort(List), FilteredList = filter(SortedList), List3 = do_something_with(FilteredList), List4 = another_thing_with(List3) 

In Elixir, you could just write:

list = sort(list) list = filter(list) list = do_something_with(list) list = another_thing_with(list) 

This is exactly the same, but it looks a little better. Of course the best solutions would be to write like this:

list |> sort |> filter |> do_something |> another_thing_with 

Every time, you assign new thing to list variable, you get new instance:

iex(1)> a = 1 1 iex(2)> b = [a, 2] [1, 2] iex(3)> a = 2 2 iex(4)> b [1, 2] # first a did not change, it is immutable, currently a just points to something else 

You just say, that you are no longer interested in the old a and let it point to something else. If you are coming from Erlang background, you probably know the f function from shell.

A = 1. f(A). A = 2. 

In Elixir you just don't have to write the f. It is done automatically for you. This means, that every time, you have variable on the left side of the pattern match, you are assigning new value to it.

Without the ^ operator, you wouldn't be able to have a variable on the left side of pattern match, because it would get new value from the right side. ^ means do not assign new things to this variable - treat it as a literal value.

That is why in Elixir

x = 1 [1, x, 3] = [1, 2, 3] 

is equivalent in Erlang to:

X = 1, [1, CompletelyNewVariableName, 3] = [1, 2, 3] 

and:

x = 1 [1, ^x, 3] = [1, 2, 3] 

is equivalent to:

x = 1 [1, 1, 3] = [1, 2, 3] 

which in Erlang is:

X = 1, [1, X, 3] = [1, 2, 3] 
like image 73
tkowal Avatar answered Oct 12 '22 10:10

tkowal