Skip to content

Instantly share code, notes, and snippets.

@bmitch
Last active February 13, 2023 11:24
Show Gist options
  • Save bmitch/1309dd42d3f87f66bf54a932132af82e to your computer and use it in GitHub Desktop.
Save bmitch/1309dd42d3f87f66bf54a932132af82e to your computer and use it in GitHub Desktop.
elixir-pattern-matching.md

Back

Pattern Matching

  • = is not assignment in Elixir. More like an assertion.
  • Succeeds if it can find a way of making left side equal to right side.
a = 1 #1
a + 3 #1

In thise cases the lef side is a variable and right side is an integer literal. So to make the match it binds the variable to the integer.

a = 1 #1
1 = a #1
2 = a # (MatchError) no match of right hand side value: 1

2 = a raises an error. Elixir only changes left hand side of the =

list = [ 1, 2, 3] # [1, 2, 3]

Elixir bound the variable list to [1, 2, 3]

Example where a list of variables gets bound to values:

list = [1, 2, 3] # [1, 2, 3]
[a, b, c] = list # [1, 2, 3]
a # 1
b # 2
c # 3
list = [1, 2, [3, 4, 5] ] 
# [1, 2, [3, 4, 5]]

[a, b, c] = list 
# [1, 2, [3, 4, 5]]
a # 1
b # 2
c # [3, 4, 5]

In this example the literal 2 in the pattern matched the corresponding term on the right so the match succeeds by setting the values of a and b to 1 and 3.

list = [1, 2, 3]
#[1, 2, 3]

[a, 2, b] = list
#[1, 2, 3]

a #1
b #3

In the second attempted match, the second term (1) cannot be matched against the corresponding element on the right side (2) so no variales are set and the match fails.

list = [1, 2, 3]
# [1, 2, 3]

[a, 1, b] = list
** (MatchError) no match of right hand side value: [1, 2, 3]

Ignoring a Value

You can use the _ to ignore a value during the match. Acts as a variable but discards any value given to it. Basically a wildcard.

[1, _, _] = [1, 2, 3]
# [1, 2, 3]

[1, _, _] = [1, "cat", "dog"]
# [1, "cat", "dog"]

Can only bind variables once per match

First expression works because a is matched with the first 1 on the right side. The value in a then used in the second term to match the second 1 on the right.

[a, a] = [1, 1]
# [1, 1]

a #1

In this expression the first b matches the 1 but the second b corresponds to 2 on the right. b cannot have two different values so fails.

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

But you can bind a variable to a new value in a subsequent match:

a = 1 #1
[1, a, 3] = [1, 2, 3]
# [1, 2, 3]
a # 2

You can force Elixir to use the existing value of the variable in the pattern with a ^ (the pin operator).

a = 1 #1
a = 2 #2
^a = 1
** (Match Error) no match of right hand side value: 1
a = 1 #1
[^a, 2, 3] = [1, 2, 3]
# [1, 2, 3]
a = 2 #2
[^a, 2] = [1, 2]
** (MatchError) no match of right hand side value: [1, 2]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment