ELIXIR / CHAPTER 04
Function clauses and guards
IntermediateExpress domain cases with ordered patterns and supported guard checks.
By the end of this chapter
- Define a named module function
- Order specific clauses before general ones
- Use guards to constrain matched input
The idea
Enter with tuples, atoms, and pattern matching understood. Named functions live in modules and may have several clauses with the same name and arity. Elixir selects the first clause whose pattern and guard match. This makes tagged success and failure values convenient to process directly. A general clause placed too early can hide more specific behavior later in the definition.
Guards refine the accepted values using a restricted set of operations. Checks such as is_integer and numeric comparisons can state a function’s domain clearly. They are not places for arbitrary user-defined function calls. Keep invalid input behavior intentional: provide a fallback when the public contract permits it, or clearly document a narrower accepted domain. The examples use explicit fallback values so the decision is visible.
defmodule Ticket do
def label(n) when is_integer(n) and n > 0, do: :valid
def label(_), do: :invalid
end
IO.inspect({Ticket.label(3), Ticket.label(0)}){:valid, :invalid}Three satisfies both guard checks. Zero reaches the fallback because it is not strictly positive.
Try it yourself
Define a function with separate clauses for {:ok, value} and {:error, reason}.
Use your own editor for this exercise. Runnable challenges on CodeQuest are available for JavaScript, Python, and SQL.
CHECK YOUR UNDERSTANDING