Control Flow in Elixir
Learn how to direct program flow in Elixir using if/else, case, cond, guards, pattern matching, and recursion with Docker-ready examples
Control flow is how a program decides what to do next. Most languages reach for if, for, and while to make those decisions. Elixir has if, but as a multi-paradigm functional language it leans on tools that fit immutable data far better: pattern matching, multi-clause functions, case, cond, guards, and recursion.
The biggest mental shift is that Elixir has no mutable loop counters. You can’t write i = i + 1 because data is immutable. Instead, iteration is expressed through recursion or through the Enum and comprehension constructs that wrap it. Branching, meanwhile, is often handled by matching the shape of data rather than testing it with conditionals.
In this tutorial you’ll learn how Elixir handles conditionals (if, unless, case, cond), how guards add conditions to pattern matches, and how recursion replaces the traditional loop. Every example runs as a standalone .exs script.
If, Unless, and Expressions
Elixir does have if and unless, and unlike many languages they are expressions — they return a value you can assign.
Create a file named if_else.exs:
| |
Note the inline do:/else: form — handy for short, one-line conditionals.
Case: Matching on Shape
case compares a value against a series of patterns and runs the first branch that matches. This is the idiomatic replacement for the switch statement, and it does far more because each pattern can destructure data. The _ pattern is a catch-all.
Create a file named case_match.exs:
| |
Here :red and friends are atoms — constants whose value is their own name, commonly used as labels in Elixir.
Cond and Guards: Choosing on Conditions
When you need to branch on arbitrary boolean conditions rather than match a single value, use cond — it behaves like an if/else-if chain. The first condition that evaluates to a truthy value wins, and true serves as the default branch.
Guards (when) let you attach conditions directly to function clauses, so the right clause is selected automatically without any conditional inside the body.
Create a file named cond_guards.exs:
| |
Recursion: Looping the Functional Way
Elixir has no for or while loop that mutates a counter. Repetition is expressed through recursion. Multi-clause functions make this clean: one clause defines the base case that stops the recursion, another does the work and calls itself with a smaller argument.
Create a file named recursion.exs:
| |
Pattern matching on the literal 0 chooses the stopping clause automatically — no explicit if needed to check whether to continue.
Enum, Comprehensions, and With
In day-to-day code you rarely write raw recursion. The Enum module and list comprehensions wrap it for you, and the with expression chains pattern matches together, short-circuiting as soon as one fails.
Create a file named iteration.exs:
| |
inspect/1 turns the list into its source representation so it prints cleanly inside a string.
Running with Docker
You can run every example without installing Elixir locally.
| |
Expected Output
Running if_else.exs:
You are an adult
Age is not zero
Status: working age
Running case_match.exs:
Stop
Go
Unknown signal
Running cond_guards.exs:
A
B
F
It is Warm
Running recursion.exs:
3
2
1
Liftoff!
Running iteration.exs:
Line 1
Line 2
Line 3
Evens: [2, 4, 6, 8, 10]
Access granted
Key Concepts
if/unlessare expressions — they return a value, so you can assign the result directly instead of mutating a variable.casematches shape — it compares a value against patterns and destructures data in the same step, replacing the traditionalswitch.condchains conditions — use it when branches depend on arbitrary boolean tests rather than a single value;trueis the catch-all.- Guards (
when) select clauses — attaching conditions to function clauses pushes branching into the function head, keeping bodies clean. - Recursion replaces loops — with no mutable counters, repetition is expressed by a function calling itself toward a base case.
Enumand comprehensions wrap recursion for everyday iteration and filtering over collections.withshort-circuits a sequence of pattern matches, running its body only when every step succeeds and falling through toelseotherwise.- Pattern matching over conditionals — matching the structure of data (like the literal
0) often eliminates the need for explicitifchecks.
Running Today
All examples can be run using Docker:
docker pull elixir:1.17-alpine
Comments
Loading comments...
Leave a Comment