Guard clauses in Elixir

Guard clauses in Elixir allow us to extend the standard parameter pattern match to evaluating against a predicate.

For example

defmodule Guard do
  def check(value) when value == nil do
    IO.puts "Value is nil"
  end

  def check(value) when is_integer(value) or is_float(value) do
    IO.puts "#{value} is number"
  end

  def check(value) when is_atom(value) do
    IO.puts "#{value} is atom"
  end

end

We can see the use of the when keyword, also for multiple guards we use the or keyword. The right side of the when clauses is a predicate, hence should return true or false.

In these examples if we enter Guard.check(nil) the result is “Value is nil” if you check 123 or 123.4 (for example) the second guarded function is called etc.

Now one must remember that Elixir will evaluate functions from the top to the bottom, hence if the is_atom check is moved to the top of the functions, a nil will match as an atom and hence never reach the “Value is nil” returning function.

As we’ve seen, we supply a predicate to the function which means we can check the value for things like it’s type. We can also handle ranges, for example maybe we have one function that handle division but guards against a denominator of 0, then we might create two functions like this

def div(a, b) when b == 0 do
  if b == 0, do: raise("Divide by Zero")
end

def div(a, b) do
  a / b
end

I’m not saying this is better than writing something like the code below, but it’s another way of doing things

def div(a, b) do
  if b == 0, do: raise("Divide by Zero")

  a / b
end

As we saw, we use or not ||.

  • The boolean operators allowed are or, and, not and !.
  • Comparison operators include ==, !=, ===, >, <, >= and <=.
  • Arithmetic operators +, , *, / can be used.
  • Join operators <> and ++ can be used.
  • The in operator can be used.
  • Type check functions such as is_integer etc.

For a more complete list which also include “guard-friendly functions” such as abs etc. can be viewed in the Guards documentation