DEV Community

TK
TK

Posted on • Originally published at leandrotk.github.io

Elixir Learnings 002: playing around with lists

This is part of my series on Elixir Learnings, where I share micro-posts about everything I'm learning related to Elixir.

Today we going to play around with lists. At the same time lists are very simple, they are powerful. And we use it always in our day-to-day work. Here we will understand some common concepts we need to handle lists.

Add and remove items

We have two ways to add new items to the list. We can use the insert_at List function and the ++ operator to concat lists.

The insert_at function receives three parameters: the list, the index position you want to add the new item, and the item.

items = [1 ,2 ,3 ,4]
List.insert_at(items, 0, 0) # [0, 1 ,2 ,3 ,4]
List.insert_at(items, 4, 5) # [1 ,2 ,3 ,4, 5]
Enter fullscreen mode Exit fullscreen mode

And Elixir lists are immutable. After these operations, if we call the items again, it will be the first value.

items # [1 ,2 ,3 ,4]
Enter fullscreen mode Exit fullscreen mode

The list value doesn't change.

We can also use the ++ operator to concat lists to add a new item.

brothers = ['TK', 'Yuji', 'Bruno']
new_brother = 'Kaio'
brothers ++ [new_brother] # ['TK', 'Yuji', 'Bruno', 'Kaio']
Enter fullscreen mode Exit fullscreen mode

Not only one item. But concat any list.

['TK', 'Kaio'] ++ ['Yuji', 'Bruno'] # ['TK', 'Kaio', 'Yuji', 'Bruno']
Enter fullscreen mode Exit fullscreen mode

With the -- operator, we can subtract a list of items from the left list.

bookshelf = ['HP', 'Compound Effect', 'Enlightenment Now']
bookshelf -- ['HP'] # ['Compound Effect', 'Enlightenment Now']
Enter fullscreen mode Exit fullscreen mode

Getting items

I learned simple but very useful functions to get items: first and last.

List.first([1, 2, 3]) # 1
List.last([1, 2, 3]) # 3
Enter fullscreen mode Exit fullscreen mode

We can also handle empty lists:

List.first([]) # nil
List.last([]) # nil
Enter fullscreen mode Exit fullscreen mode

Make it flat

Another cool function is flat. It flats nested lists. In other words, it transforms nested lists into just one with all the elements.

  • Not so nested lists
List.flatten([1, [2], [3]]) # [1, 2, 3]
Enter fullscreen mode Exit fullscreen mode
  • More complex nested lists
List.flatten([1, [[2, [3]]]]) # [1, 2, 3]
Enter fullscreen mode Exit fullscreen mode
  • Nested empty lists
List.flatten([[], [[], []]]) # []
Enter fullscreen mode Exit fullscreen mode

Iterate through it

One thing we always do with lists is iteration. We can use the each function from the Enum module to loop through the list.

items = [1, 2, 3, 4, 5]
Enum.each(items, fn (n) -> IO.inspect(n) end)
Enter fullscreen mode Exit fullscreen mode

And we can also use a shortcut for functions.

Enum.each(items, &IO.inspect/1) # shortcut
Enter fullscreen mode Exit fullscreen mode

The Enum module has various other functions to work on data types, like lists, that implements the Enumerable protocol.

Destructuring

Another way to get items from the list is called destructuring. We unpack items from the list by specifying the "variables" inside a list.

[a, b, c] = [1, 2, 3]
IO.inspect a
IO.inspect b
IO.inspect c
Enter fullscreen mode Exit fullscreen mode

With the [a, b, c], we are specifying the variable names to destructure the list.

If you want to get only the second item, use the _ operator (also called wildcard).

[_, x, _] = [1, 2, 3]
IO.inspect x # 2
Enter fullscreen mode Exit fullscreen mode

Another interesting way to get items is by using the | operator. With this operator, we get the head (first item) and the right part represents the other items.

[head | rest] = [1, 2, 3, 4, 5]
IO.inspect head # 1
IO.inspect rest # [2, 3, 4, 5]
Enter fullscreen mode Exit fullscreen mode

But it's not just about the first element. We can specify more than just the first item.

[first, second | rest] = [1, 2, 3, 4, 5]
IO.inspect first # 1
IO.inspect second # 2
IO.inspect rest # [2, 3, 4, 5]
Enter fullscreen mode Exit fullscreen mode

Lists are linked lists in Elixir. The last node points to an empty list.

[head | rest] = [:a]
IO.inspect head # :a
IO.inspect rest # []
Enter fullscreen mode Exit fullscreen mode

This is why when we get the rest, it is an empty list.

Wrapping up

Lists have the wrap function to transform values into a list. It wraps the value in a list.

List.wrap("TK") # ["TK"]
List.wrap(1) # [1]
List.wrap(true) # [true]
List.wrap(:ola) # [:ola]
Enter fullscreen mode Exit fullscreen mode

We can also wrap a list. But it just returns the same list.

List.wrap([1, 2, 3]) # [1, 2, 3]
Enter fullscreen mode Exit fullscreen mode

nil is also a value. It represents the absence of a value. When we wrap it, the function returns an empty list.

List.wrap(nil) # []
Enter fullscreen mode Exit fullscreen mode

Resources

Top comments (0)