# Whats the purpose of using the "Head and tail" Syntax?

Hello,

Learning about the Lists and I came across pattern matching using the Head and Tail Syntax. [Head | Tail] = [1, 2, 3, 4, 5]. is this similar to arrays in JS? What would I need to use this for if its suppose to be immutable?

2 Likes

It is very much not similar to arrays in most languages, as arrays can usually access any element in the same amount of time.

Lists are linked lists, so accessing the Nth element requires looking at the first N-1. `[1,2,3,4,5]` is a shorthand way of writing `[ 1 | [ 2 | [ 3 | [ 4 | [ 5|[]]]]]]`

The Erlang manual has a short discussion

A very common idiom in Elixir is pattern-matching on the head and then recursing with the tail, for instance:

``````def double([]), do: []
def double([head | tail]) do
[2 * head | double(tail)]
end
``````

Note that writing this code in this way in some languages would be a performance problem, since `double` would need a lot of stack space for intermediate results. Erlangâ€™s VM knows how to optimize this sort of pattern into a memory-efficient instruction sequence, so you may not have to worry about tail-recursion.

7 Likes

Lists in Elixir are linked lists which come with some tradeoffs. For example, prepending to a linked list is fast whereas appending is slow.

Regarding the ability to pattern matching the head and tail of a list, it comes in handy especially with recursion.

``````defmodule Math do
def sum_list([head | tail], accumulator) do
sum_list(tail, head + accumulator)
end

def sum_list([], accumulator) do
accumulator
end
end

IO.puts Math.sum_list([1, 2, 3], 0) #=> 6
``````

Just wanted to highlight that the `sum_list` example above intentionally includes an additional accumulator parameter to optimize for tail recursion because there are optimizations when the result is not a list as noted in the erlang docs link shared by @al2o3cr.

4 Likes

Just to throw a tiny bit more stuff at you to maybe help understand its power, you arenâ€™t limited to matching just head and tail, you can do things like:

``````[a, b | rest] = [1, 2, 3, 4, 5]
a #=> 1
b #=> 2
rest #=> [3, 4, 5]
``````

I wonâ€™t throw more code at you right now but, for example, you could use that to write a function that iterates over each neighbouring pair in a list (`1,2`, `2,3`, `3,4`, and `4,5`).

7 Likes

The first week or two of Advent of Code is great practice for fundamentals. Day 5 is good for lists.