When discussing pattern matching in Elixir (and other languages), it seems like most of what people talk about isn’t the actual matching part.

Pattern Matching

Pattern matching is the ability to check if the left and right match.

iex(1)> 1 = 1
1

iex(2)> 2 = 1
** (MatchError) no match of right hand side value: 1

It is sensitive to data types.

iex(1)> [] = []
[]

iex(2)> [] = {}
** (MatchError) no match of right hand side value: {}

It checks the shape of the data as well.

iex(1)> {1} = {1}
{1}

iex(2)> {} = {1}
** (MatchError) no match of right hand side value: {1}

It can be used to branch code.

case 1 do
  1 -> "one"
  2 -> "two"
end
"one"

That’s really all there is to it. Everything else is using pattern matching.

Using Pattern Matching

When matching, you can bind values on the LHS.

iex(1)> foo = 1
1

iex(2)> foo
1

This works in cases too.

case 1 do
  foo -> foo
end
1

You can destructure values while binding.

iex(1)> [foo, 2] = [1, 2]
[1, 2]

iex(2)> foo
1

You can ignore parts of the data.

iex(1)> [foo] = [1, 2]
** (MatchError) no match of right hand side value: [1, 2]

iex(1)> [foo, _] = [1, 2]
[1, 2]

You can use underscore as a wildcard when branching.

case "bitch" do
  "cops" -> "yep"
  "critics" -> "yep"
  "paparazzi" -> "yep"
  _ -> "ain't one"
end
"ain't one"

And finally, the ever-popular splitting of head/tail of a list.

iex(1)> [head | tail] = [1, 2, 3]
[1, 2, 3]

iex(2)> head
1

iex(3)> tail
[2, 3]