Considering the following code

0
1
2
3
4
def foo do
  x = 5
  if true, do: x = 10
  IO.inspect x
end

Calling this will output 5.

0
1
2
iex()> foo()
5 # the inspect value
5

Why is this?

We know that Elixir is a functional language and, therefore most things we see in Elixir are functions. For example, both def and defmodule are functions. And within functions, we cannot change variables outside the functions.

0
1
2
3
4
5
6
7
8
def foo do
  x = 5
  bar()
  puts x
end

def bar do
  x = 10
end

This will output 5, which surprises no one, and to change the x in foo we could write:

0
1
2
3
4
5
6
def foo do
  x = 5
  x = bar()
  puts x
end

def bar, do: 10

In Elixir the if statement is a function with an arity of two. And it becomes evident we should write the following to update x.

0
1
2
3
4
def foo do
  x = 5
  x = if true, do: x = 10 # same functionality as bar()
  puts x
end

This is also the reason why we have to use <%= instead of <% in eex templates.

0
1
2
<%= if condition do %>
  # ...
<% end %>

Since if/2 is only conditionally returning the value inside the block.