> If variables don't mutate
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.