Yes it is. x is the variable. It changed from 1 to 2. Mutation is a synonym for change. Try it yourself in the interpreter! So data is immutable, but variables are mutable in Elixir.
Dude that's not a mutation that's a rebinding. You do not understand the difference, and it is an important one.
Again, Elixir does not create mutation where in Erlang there was none. There is no mutation.
They decided to allow rebinding so that you wouldn't end up with a whole bunch of stupid temporary variables, which is exactly what you have to do in Erlang.
That is a variable mutation. Mutation is a change in value. x was 1 then it was 2. If that is not mutation, I don't know what is.
You are probably trying to say that Elixir and Erlang have immutable data. But that's what that's called "immutable data". Precisely because the variables can be mutated or not separately from the data.
> a whole bunch of stupid temporary variables, which is exactly what you have to do in Erlang.
Well we should tell Joe that it's stupid. Maybe he'll change his mind.
If variables don't mutate, all it means is that the memory location that stores the value of that variable is guaranteed to never change. Thus, if you reassign that same-named variable, it actually points to a new memory location with the new value. That is what "rebinding" is vs. "mutating." The advantage of this is concurrency, etc. etc. The disadvantage is you have to have good GC since you'll be doing a lot more garbage collection. It may LOOK like it's changing a variable, but it's not- the variable merely points to a new memory location.
Other languages, like Ruby, do not work this way. If you reassign an instance variable, the memory that is storing that value actually does change.
Here, compare the same sequence of operations in Ruby and Elixir, first Ruby:
bash>> irb
>> a = {a: 5}
=> {:a=>5}
>> b = a
=> {:a=>5}
>> a[:a] = 10
=> 10
>> b
=> {:a=>10}
and now Elixir:
bash>> iex
Erlang/OTP 18 [erts-7.1] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Interactive Elixir (1.1.0) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> a = %{a: 5}
%{a: 5}
iex(2)> b = a
%{a: 5}
iex(3)> a = %{a | a: 10} # updates a mapping
%{a: 10}
iex(4)> b
%{a: 5}
Notice how b's value changed in Ruby, but not in Elixir. In both cases, the hash was updated.
I think we are talking about two different things when we say "variables". When I say "variable" I mean x, y, a, b etc. That is the variable. It has a value, you can see it in the shell (repl) or when printing it. Look at what happens to variable x:
iex(1)> x=1
1
iex(2)> x=2
2
It was 1 then 2. It changed. Mutation is a synonym for "change". I think it is a pretty simple concept. Did the framework create a new memory cell, put a 2 in there and now x behind the scene dereferences that. Did it update the old cell in place. Was it on the stack? That's not the point. The point is x now has a new value. x is a variable that means variable x mutated.
Compare to Erlang:
1> X=1.
1
2> X=2.
** exception error: no match of right hand side value 2
You can't mutate variable X. variable X is immutable. Again, I think that is pretty clear and simple.
What you showed in your example is how data is immutable in Elixir but not in Ruby.
> The advantage of this is concurrency, etc. etc.
Actually most data, except larger binaries, are copied between processes anyway. So concurrency advantage is mostly theoretical. In the future they could be switched to reference counting for other things. But that is a hidden implementation detail anyway.
Everywhere pretty much. Learn a bit more how it works. Here is a good resource:
http://elixir-lang.org/getting-started/introduction.html
Here is an example:
x was 1, then it was 2. It mutated.To compare here is Erlang:
Just like in math, once X=1, it stays that. It doesn't get to mutate.