Elixir Fundamentals: Functional Programming and OTP · Functional Elixir: Data, Pattern Matching and Functions
Pattern Matching: The = Operator Is a Match
In Elixir, = matches a pattern against data and binds variables. Destructure tuples, lists and maps, use the pin operator ^ to match an existing value, and handle {:ok, value} and {:error, reason} results.
What you'll build
A response handler that pulls data out of tuples, lists and maps with patterns, and reacts differently to {:ok, ...} and {:error, ...} results.
The idea
= is the match operator. Elixir checks that the shape on the left matches the data on the right, binding any variables:
{:ok, user} = {:ok, "ana"} # user = "ana"
[first | rest] = [1, 2, 3] # first = 1, rest = [2, 3]
%{name: name} = %{name: "Ana", age: 34} # partial map match
If the shapes don't match, you get a MatchError. That's a feature: code asserts the shape it expects.
_ignores a value:{_, count} = {:ignored, 3}.- The pin operator
^xmatches against the current value ofxinstead of rebinding it. - Elixir's convention for results is tagged tuples:
{:ok, value}or{:error, reason}. Pattern matching makes handling both cases natural.
Patterns appear everywhere: function heads, case, with, and receive.
The code
{:ok, user} = {:ok, %{name: "Ana", role: :admin, langs: ["Elixir", "Go", "Rust"]}}
%{name: name, langs: [first_lang | other_langs]} = user
IO.puts("#{name} likes #{first_lang} (and #{length(other_langs)} more)")
{status, code, _headers} = {:http, 200, ["content-type: json"]}
IO.puts("#{status} #{code}")
expected = 200
case {:http, 404} do
{:http, ^expected} -> IO.puts("as expected") # ^ matches the current value of `expected`
{:http, other} -> IO.puts("unexpected status #{other}") # `other` binds anything else
end
results = [{:ok, 3}, {:error, :timeout}, {:ok, 5}, {:error, :not_found}]
for result <- results do
case result do
{:ok, value} -> IO.puts("ok: #{value}")
{:error, :timeout} -> IO.puts("retrying after timeout")
{:error, reason} -> IO.puts("failed: #{reason}")
end
end
try do
{:ok, _} = {:error, :boom}
rescue
e in MatchError -> IO.puts("MatchError: #{inspect(e.term)}")
end
Output
Ana likes Elixir (and 2 more)
http 200
unexpected status 404
ok: 3
retrying after timeout
ok: 5
failed: not_found
MatchError: {:error, :boom}Run this on your computer — see “Get Started” for setup.
Common mistakes
- Thinking
=is assignment. It's a match; the left side is a pattern. - Rebinding by accident inside a pattern when you meant to compare; use
^var. - Over-specific matches on maps:
%{a: x}matches maps with at least key:a, which is usually what you want. - Ignoring
{:error, _}. Handle both shapes, or let it crash deliberately (see the OTP lessons).
Key points
=matches shapes and binds variables; mismatches raiseMatchError.- Destructure tuples, lists (
[head | tail]) and maps (partial matches). ^pins an existing value;_ignores.- Tagged tuples
{:ok, v}/{:error, r}are the result convention.
Further reading: Pattern matching.
Practice questions
What does the pin operator ^ do?
Answer
In a pattern, ^x matches against the current value of x instead of rebinding x to whatever is on the right side.
What does [head | tail] = [1, 2, 3] bind?
Answer
head is 1 and tail is [2, 3]. The | splits a list into its first element and the remaining list.
Open in the app to mark lessons complete, take notes and track your progress.