Appearance
Pattern matching
Source: Elixir guide, Pattern matching.
This chapter explains why = is called the match operator, how to pattern match inside data structures, and how the pin operator ^ accesses a value that is already bound.
The match operator
= looks like assignment, but it is a match. The two sides must be equal:
elixir
x = 1
1 = x #=> 1
2 = x #=> ** (MatchError) no match of right hand side value: 11 = x is a valid expression: both sides are 1, so it matches. When they aren't equal, Elixir raises MatchError.
A variable can only be assigned on the left of =:
elixir
1 = unknown
#=> ** (CompileError) iex:1: undefined variable "unknown"Pattern matching
The match operator also destructures complex data types. Tuples first:
elixir
{a, b, c} = {:hello, "world", 42}
a #=> :hello
b #=> "world"Both sides are three-element tuples, so they line up field by field. Each variable takes the value opposite it.
If the sides can't line up, the match fails. That happens when the sizes differ, or when the types differ (a tuple on the left, a list on the right):
elixir
{a, b, c} = {:hello, "world"}
#=> ** (MatchError) no match of right hand side value: {:hello, "world"}
{a, b, c} = [:hello, "world", 42]
#=> ** (MatchError) no match of right hand side value: [:hello, "world", 42]You can also match on specific values. This pattern only matches a tuple that starts with the atom :ok:
elixir
{:ok, result} = {:ok, 13}
result #=> 13
{:ok, result} = {:error, :oops}
#=> ** (MatchError) no match of right hand side value: {:error, :oops}:ok is a literal, so it has to equal :error. It doesn't, so the match stops there and result is never bound.
Lists
Lists work the same way: [a, b, c] = [1, 2, 3] binds a to 1, and so on.
A list can also be matched on its own head and tail:
elixir
[head | tail] = [1, 2, 3]
head #=> 1
tail #=> [2, 3]A list is a chain of cells, each holding a value and a pointer to the rest. [head | tail] splits off the first cell: head is its value, tail is everything after it.
Like hd/1 and tl/1, this can't match an empty list:
elixir
[head | tail] = []
#=> ** (MatchError) no match of right hand side value: []The [head | tail] form isn't only for matching. It also prepends to a list:
elixir
list = [1, 2, 3]
[0 | list] #=> [0, 1, 2, 3]Ignoring values with _
When you don't care about part of a pattern, bind it to _. If only the head matters, throw the tail away:
elixir
[head | _] = [1, 2, 3]
head #=> 1_ can never be read. Using it in an expression is a compile error:
elixir
_
#=> ** (CompileError) iex:1: invalid use of _. "_" represents a value to be ignored in a pattern and cannot be used in expressionsThe same variable twice
If a variable appears more than once in a pattern, every occurrence must bind to the same value:
elixir
{x, x} = {1, 1} #=> {1, 1}
{x, x} = {1, 2} #=> ** (MatchError) no match of right hand side value: {1, 2}Limits
Pattern matching is powerful but limited. You can't call functions on the left side of a match:
elixir
length([1, [2], 3]) = 3
#=> ** (CompileError) iex:1: cannot invoke remote function :erlang.length/1 inside matchDestructuring is one of the foundations of recursion in Elixir, and it applies to other types too, like maps and binaries.
The pin operator
Variables can be rebound:
elixir
x = 1
x = 2Sometimes you don't want that. Use the pin operator ^ to match against a variable's existing value instead of rebinding it:
elixir
x = 1
^x = 2
#=> ** (MatchError) no match of right hand side value: 2Since x was pinned while bound to 1, that is equivalent to 1 = 2, and you get the exact same error message.
The pin also works inside other patterns, such as lists and tuples:
elixir
x = 1
[^x, 2, 3] = [1, 2, 3] #=> [1, 2, 3]
{y, ^x} = {2, 1} # y = 2
{y, ^x} = {2, 2} #=> ** (MatchError) no match of right hand side value: {2, 2}Because x was 1 when it was pinned, the last line could have been written {y, 1} = {2, 2}.
Next, case, cond, and if shows patterns picking a branch, and they can be extended with guards.