Since everything in Elixir is an expression, and if is no exception, the if…else construct returns a value that we can assign to a variable for later use:
if suppose you want to change any variable value inside if block in Elixir. You need to get back and re-assign the value to the same variable.
This is the code you will expect to work. But it won’t.
iex(7)> a = 5
5
iex(8)> is_odd = nil
nil
iex(9)> if rem(a, 2) == 0 do
...(9)> is_odd = false
...(9)> else
...(9)> is_odd = true
...(9)> end
warning: variable "is_odd" is unused (if the variable is not meant to be used, prefix it with an underscore)
iex:12
warning: variable "is_odd" is unused (if the variable is not meant to be used, prefix it with an underscore)
iex:10
true
iex(10)> is_odd
nil
So you need to re-assign it back like below:
iex(13)> a = 5
5
iex(14)>
nil
iex(15)> is_odd = if rem(a, 2) == 0 do
...(15)> false
...(15)> else
...(15)> true
...(15)> end
true
iex(16)> is_odd
true
iex(17)>
Welcome to the immutable data structure land. Most data in elixir is immutable, in other words, you can’t change the value of a variable. Instead, you can create a new const using old name.
iex(1)> a = 1
1
iex(2)> if true, do: a = 2
warning: variable "a" is unused (if the variable is not meant to be used, prefix it with an underscore)
iex:2
2
iex(3)> a
1 # didn't change
iex(4)> a = if true, do: 2
2 # new value with old name
That’s not really the case for what you show. Your examples work the way they do, because of the lexical scoping rules within elixir. Earlier versions of elixir (until 1.2 iirc) did work differently and allowed rebinding of variables within if blocks. There’s no mutability in both versions though, as that one is enforced by the beam.
So while it might seem related it actually is not.