I have a fairly simple question and cant seem to understand it.
for example we have the following code:
x = 1
x = 2
IO.puts x
since elixir is immutable, why does this print 2?
now i know that elixir doesnt make any change directly to x and in fact x = 2 is does on a copy of the variable x = 1. Then how can we get the original value for x, which is 1?
Immutability is independent from assignments â the act of creating the relationship between variable and the value it represents. Immutability only means your values (in memory) will never be modified. It doesn not mean that the variable x will always represent the same value. Once you changed what x points to thereâs no way to get the value it pointed to before (even when it might still exist in memory).
the example you provided means that value of x is being changed scope wise. For example:
x = 1
if some_true_value do
x = 2
IO.puts x # -> will output 2.
end
IO.puts x # -> will output 1.
so like in Rust, it gives an error and also gives you the option to declare a variable mutable or immutable, should we be getting an error when we something like the code i posted?
Another example which you might run in to when you are new to Elixir or immutabillity in general, is that you actually forget to reassign, e.g. when using lists and maps.
alright, so that means that values can be overwritten in elixir for variables but memory wise the values stay the same? can you please explain with an example
this I understand. The same concept is used when working with for loops in elixir, or when using sockets in live views and you have to do something like this for example
Indeed. As for the example, I am no expert in Elixir either⊠But what I understand is that values get assigned to variables and get scoped into the block they are defined in.
So
x = 1 # variable x is created and the value 1 is assigned
x = 2 # variable x is reassigned with value 2, same memory address
if :foo == :foo do
x = 3 # variable x is created inside if block, think of the name as x'
end
# here x is still 2, x' from inside the if block is gone.
its a good answer but sadly still doesnt answer my question.
@LostKobrakai and @jeroenbourgois I think immutability means that whatever variable we are creating can be changed but when we look at it in the view of a process then their states cannot be changed once they are running. I saw this video and in this he explains that actually a copy is being made which is used but the original data stays the same.
Maybe something more along the lines of this will help:
a = [:bears, :elephants]
b = a
a = Enum.reject(a, fn animal -> animal == :bears end)
IO.inspect(a)
IO.inspect(b)
So we make a point to some value, and then make b point to the same thing as a. Then we call Enum.reject the result of which a gets rebound to. The reject call creates a new list based on what a was originally bound to: it cannot modify what a was originally bound to since that original list is immutable. b is still bound to the original list that a was originally bound to. Since that original list is immutable, we can make assumptions about b without concern with what happens to a later on. a itself may be rebound, but that original list of [:bears, :elephants] is not changed as a result.
Love these examples @hauleth and @sbuttgereit. I have a good grasp on this but never know how to explain it to people in a way theyâll accept. I think these will helpâthanks!
Different languages have different meanings for things.
Iâm most comfortable with juliaâs definitions, where they make a distinction between variable and value. The variable is the lexical representation in code, and value is the value that the machine sees (the stuff in memory, if you will).
In this lexicon (which I think corresponds more to what we typically mean in math and CS), in Elixir, the variable is mutable but the value is immutable. You can âpointâ your variable at a different value (ârebindingâ), but this does not change the underlying values. If a different variable is holding onto the underlying value, then it is unaffected by the rebinding event.
Note that in the Elixir docs and the elixir community, we have a different meaning of variable, hopefully pointing this out will help you instead of confusing you.
In a nutshell: you can repoint x to a new value, but you canât change the value x is currently pointing at.
Integers are not generally mutable in any language, so this is not a great example to demonstrate Elixirâs immutability with. Something thatâs very mutable in other languages are collections, but in Elixir you cannot mutate a collection. Ie. in Elixir thereâs no way to push a new value onto an existing list/tuple/map, instead you are always creating a new collection. Eg.
iex(22)> x = y = { 1, 2 }
{1, 2}
iex(23)> x = Tuple.insert_at(x, 0, :foo)
{:foo, 1, 2}
iex(24)> x
{:foo, 1, 2}
iex(25)> y
{1, 2}
Notice how we can reassign the new tuple we created with the new element inserted to x, but the tuple x had originally been pointing at (also assigned to y) remained unchanged.
So first accept that Elixir is immutable, which means variables cannot change, and values and data structures cannot change. Then work back from there.
So in your example, x = 1 and x = 2 seems contrary to immutability. But like others said, it is because these are actually two different variables.
The consequence is that you cannot do typical counting/summing using mutable methods, e.g.:
// This typical JavaScript way of summing would not work in Elixir due to immutability
function sumAll(list) {
let sum = 0;
for (let item of list) sum += item;
return sum;
}
Hi,
The concept of Immutability in Elixir is value of any variable(in memory) will never modified.
For example,
x = 1
x = 2
When we print x, itâll print 2. It doesnât means x modified its value but in memory new value(2) allocate to variable x.
Think of a variable as a label applied to a value. The label can be pulled off and placed on some other value; but the value itself cannot change. That is a fundamental property of the Erlang VM.
You can think of the = operator as the label operator. Itâs not copying the value into a box for the variable name: the variable name is pointing to the actual value.
Check out this code
x = 1
y = 1
In that code x and y arenât holding two copies of 1: they are each pointing to the same immutable value of 1. When you ârelabelâ x = 2 you are pulling the âxâ label off of the value 1 and applying it to the value 2.
Maybe using strings will make it more clear.
> x = "abc"
"abc"
> x <> "def"
"abcdef"
> x
"abc"
When we concatenated âdefâ onto the variable âxâ we did not change its value and we did not reapply the label âxâ to a new value. Hence x still points to the same immutable value âabcâ
If we reapply the label âxâ to a new value
x = x <> "def"
Then the original value of âabcâ is still unchanged and immutable. But weâve pulled the label x off its original value and applied it to the new result.
Part of Immutability in Elixir is that functions are pure, they donât modify arguments or variable in place. Iâm going to do a quick contrast with Javascript.
const numbers = [4, 2, 3, 1, 23, 8, 9] numbers.sort((a, b) => a - b) console.log(numbers) // This operation has modified the numbers variable and sorted the array in ascending order.
But this is how Elixir will handle this type of problem.
After running the sort function on the variable, the value assigned to numbers variable is still the same. Elixir without modifying the numbers list just returns the sorted list which can be assigned to a new variable .