Heads and Tails

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]