Earlier we said a list may either be empty or consist of a head and a tail. The head contains a value and the tail is itself a list. This is a recursive definition.
We’ll represent the empty list like this: [ ].
Let’s imagine we could represent the split between the head and the tail using a pipe character: |. The single-element list we normally write as [ 3 ] can be written as the value 3 joined to the empty list:
| [ 3 | [ ] ] |
(I’ve highlighted the inner list.)
When we see the pipe character, we say that what’s on the left is the head of a list and what’s on the right is the tail.
Let’s look at the list [2, 3]. The head is 2, and the tail is the single-element list containing 3. And we know what that list looks like—it is our previous example. So we could write [2,3] as
| [ 2 | [ 3 | [] ] ] |
At this point, part of your brain is telling you to go read today’s XKCD—this list stuff can’t be useful. Ignore that small voice, just for a second. We’re about to do something magical. But before we do, let’s add one more term, making our list [1, 2, 3]. This is the head 1 followed by the list [2, 3], which is what we derived a moment ago:
| [ 1 | [ 2 | [ 3 | [] ] ] |
This is valid Elixir syntax. Type it into IEx.
| iex> [ 1 | [ 2 | [ 3 | [] ] ] ] |
| [1, 2, 3] |
And here’s the magic. When we discussed pattern matching, we said the pattern could be a list, and the values in that list would be assigned from the right-hand side.
| iex> [a, b, c ] = [ 1, 2, 3 ] |
| [1, 2, 3] |
| iex> a |
| 1 |
| iex> b |
| 2 |
| iex> c |
| 3 |
We can also use the pipe character in the pattern. What’s to the left of it matches the head value of the list, and what’s to the right matches the tail.
| iex> [ head | tail ] = [ 1, 2, 3 ] |
| [1, 2, 3] |
| iex> head |
| 1 |
| iex> tail |
| [2, 3] |