List
A list in elixir is denoted by square brackets [ ]
, its underlying data structure is a linked list
( single ) as opposed
to an array
. Each element (node) of the list holds reference to the next, this implies that an element of the list is likely
to be stored in a random location in memory.
A list is segemented into two (2) parts head
and tail
and can contain different datatypes but usually contains
same datatype.
[head | tail] = [:a, :b, :c, :d, :e] # => [:a, :b, :c, :d, :e]
head #=> :a
tail #=> [:b, :c, :d, :e]
[head | tail] = tail # => [:b, :c, :d, :e]
head #=> :b
tail #=> [:c, :d, :e]
["a", 1, :b, 4.5, true, [:a, :b, :c], {:ok, File }, %{name: :kofi, age: 100}]
"a" # => BitString
1 # => Integer
:b # => Atom
4.5 # => Float
[:a, :b, :c] # => List
{:ok, File } # => Tuple
%{name: :kofi, age: 100} # => Map
List Traversal
Traversing a list in elixir is expensive
as it is a linear operation O(n)
. Considering the list below, it will take
five (5) iterations to reach the end of the list.
list = [:a, :b, :c, :d, :e]
List Update
Given the list below
names = ["Alice", "Bob"]
Prepending ( | )
is fast.
names = ["John" | names] # => ["John", "Alice", "Bob"]
Appending ( ++ )
is slow.
names = names ++ ["Jane"] # => ["John", "Alice", "Bob", "Jane"]
Take Away : Updating a list can be cheap
depending on the update approach. it is therefore best practice to
prepend ( | )
instead of append ( ++ )
.
Prepending is much faster because you don’t iterate the length of the list to drop an element at the head thus
a constant time O(1)
.
On the contrary, appending is slower because to drop an element at the tail, you iterate the length of the list
hence a linear time O(n)
where n
is the length of the list.
Special Kernel Functions For Manipulating List
- hd : Returns the head of List
hd([1, 2, 3, 4, 5]) # => 1
- tl: Returns the tail of list
tl([1, 2, 3, 4, 5]) # => [2, 3, 4, 5]
Elixir list is suited for functional programming