Elixir Guards
A guard is an extra test added to a branch with the word when. The branch matches only when its pattern matches and its guard also passes.
A guard adds a size test to a type test
The first branch needs an integer that is also over 100. The value 250 passes both parts of the guard.
value = 250
label =
case value do
n when is_integer(n) and n > 100 -> "big number"
n when is_integer(n) -> "number"
_ -> "not a number"
end
IO.puts(label)Is_binary sorts text from numbers
The same value is offered to each branch in order. The text branch matches first because its guard passes.
entry = "hello"
label =
case entry do
text when is_binary(text) -> "text with #{String.length(text)} letters"
number when is_integer(number) -> "number #{number}"
_ -> "other"
end
IO.puts(label)Length in a guard measures the list
The pattern binds the whole list each time. The guard decides which branch the list may take.
items = [200, 300, 400]
label =
case items do
list when length(list) > 2 -> "long list"
list when length(list) < 3 -> "short list"
_ -> "empty list"
end
IO.puts(label)Example
reading = -25
label =
case reading do
n when is_integer(n) and abs(n) > 10 -> "far from zero"
n when is_integer(n) -> "near zero"
text when is_binary(text) -> "text reading"
_ -> "other reading"
end
IO.puts(label)Key points
- When: the word that places a guard between a pattern and its arrow.
- Double test: a guarded branch needs both the pattern match and the guard to pass.
- Type tests: is_integer and is_binary check the type of a value inside a guard.
- Size test: length inside a guard measures a list before a branch can match.
- Comparisons: guards can use the comparison operators, such as > and ==.
- Limited tools: only a small set of safe functions works in guards, such as is_integer, length, and abs.
In this example, the first pattern binds reading to n, and abs(n) is 25, so the guard passes. The case returns the first branch and never tries the rest.
Note
a failing guard sends the search to the next branch instead of raising an error.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
What does case 5 do n when is_integer(n) and n > 10 -> "big"; n when is_integer(n) -> "small number"; _ -> "other" end return?