Pattern Matching
Elixir pattern matching with = operator, tuples, lists, maps, and case/with
Pattern matching is the foundation of Elixir. The = operator is not assignment — it’s a match operator that asserts the left side equals the right side, binding variables in the process.
The match operator
x = 1 # binds x to 1
1 = x # succeeds because x is 1
2 = x # ** (MatchError) no match of right hand side value: 1Matching tuples
{:ok, value} = {:ok, 42}
value # => 42
{:error, reason} = {:ok, 42} # ** (MatchError)Matching lists
[head | tail] = [1, 2, 3]
head # => 1
tail # => [2, 3]
[first, second, third] = [10, 20, 30]
first # => 10Matching maps
%{name: name} = %{name: "Alice", age: 30}
name # => "Alice"
# Variable keys must be pinned
key = :name
%{^key => value} = %{name: "Alice"}
value # => "Alice"Pin operator ^
Prevent re-binding a variable in a match by pinning it:
x = 1
^x = 2 # ** (MatchError)
x = 2 # re-binds x to 2case
Match a value against multiple patterns:
case File.read("config.txt") do
{:ok, contents} -> IO.puts(contents)
{:error, :enoent} -> IO.puts("File not found")
{:error, reason} -> IO.puts("Error: #{inspect(reason)}")
endwith
Chain pattern matches, handling failures gracefully:
with {:ok, user} <- fetch_user(id),
{:ok, post} <- fetch_post(user),
{:ok, html} <- render_post(post) do
{:ok, html}
else
{:error, :not_found} -> {:error, "Not found"}
{:error, reason} -> {:error, reason}
endFunction heads
Define multiple clauses of a function with different patterns:
defmodule Router do
def handle(%{method: "GET", path: "/"}), do: :home
def handle(%{method: "GET", path: "/users"}), do: :users
def handle(%{method: "POST", path: "/users"}), do: :create_user
def handle(_), do: :not_found
end