In part 8 of my Elixir journey I decided to share about using guard clauses in the language.
Guard Clauses
Pattern matching allows us to side step traditional branching logic by inspecting the parameters we pass to a given function.
defmodule Math do
def add_one(n) do
n + 1
end
end
In this example, the `n` variable is our only criteria and it works great when we call `add_one` with any integer value.
Math.add_one(1)
But what happens when we call it with a string instead?
Math.add_one("x")
`ArithmeticError bad argument in arithmetic expression`
So my first thought was "I need a default function definition for `add_one` and pattern matching will come to my rescue..."
defmodule Math do
def add_one(n) do
n + 1
end
def add_one(_), do: IO.puts "yolo"
end
To my surprise I got the same `ArithmeticError`
Math.add_one("x")
It turns out the first function definition is a match for both integer and string values so pattern matching alone won't prevent us from going down that code path. This is a great use case for the guard clause in Elixir! When you need to ask a question about the parameter before you execute a function you can use the `when` keyword to further clarify what is required to use it.
defmodule Math do
def add_one(n) when is_integer(n) do
n + 1
end
def add_one(_), do: IO.puts "yolo"
end
This guard clause is using a built-in Erlang function to ask if the parameter `n` is the correct type. The order of operations here is still pattern match first, guard clause second. So in this example the match does work but the string `x` does not return truthy when the guard clause is evaluated. As a result, Elixir will attempt to match using the second `add_one` function definition. Because this function definition takes any parameter the match is a success and the `IO.puts` is executed.