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?
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?
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.
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
source: Recursion - The Elixir programming language
Edited to add:
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.
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
).
The first week or two of Advent of Code is great practice for fundamentals. Day 5 is good for lists.