DEV Community

Cover image for A List is not an Array
Diego Novais
Diego Novais

Posted on

A List is not an Array

When I saw the code below for the first time, I thought it was probably an Array. And then, it could be that you have the same thought. lol

# Creating a list
list = [1, :atom, 3, 4, "string"]
Enter fullscreen mode Exit fullscreen mode

But in Elixir, the code above it's a List.

What is a List?

In a few words, a List is Linked List. But to understand better, let's remember what an array is and then talk about the List.

About the Array

The Array is a data collection of the same type.

In the Array, we can access the content through the indices. And when we need, for example, to get the third element of an Array directly, in Ruby, we can do by passing the index number 2:

> x = [1, 2, 3, 4]
[1, 2, 3, 4]

> x[2]
3
Enter fullscreen mode Exit fullscreen mode

Another feature of the Array is that we can iterate between the elements, one by one, directly. And in Ruby, we can do by:

> x.each{|element| puts element}
1
2
3
4
Enter fullscreen mode Exit fullscreen mode

Now, let's go back to talking about List and Elixir again

In Elixir the lists are linked lists. That means each item is bound to the next element through the position in memory.

List

How can we iterate through the items in a List?

Firstly we need to know that a List is composed of 2 parts: the head is the List's first item, and the tail is the rest of the items.

In Elixir we have the kernel function hd(list) to access the first item of the List (head), and we also have the kernel function tl(list) to access the rest of the items from the List (tail). Take a look on the example below:

> # creating the List
> list = [1, :atom, 3, 4, "string"]
[1, :atom, 3, 4, "string"]

> # Return the first item of the List - Head
> hd(list)
1

> # Return the rest of items of the List - Tail
> tl(list)
[:atom, 3, 4, "string"]
Enter fullscreen mode Exit fullscreen mode

Also, it's possible to access the head and tail of a list using Pattern Matching:

# Creating a list
> list = [1, :atom, 3, 4, "string"]
[1, :atom, 3, 4, "string"]

# Using Pattern Matching to assign the first element 
# to the head and the rest of the list to the tail.
> [head | tail] = list
[1, :atom, 3, 4, "string"]

# Return the first element from the list
> head
1

# Return the rest of elements from the list
> tail
[:atom, 3, 4, "string"]
Enter fullscreen mode Exit fullscreen mode

And to iterate each item in a list, we use recursion:

# Creating the module as example
defmodule Example do
  def show_each_one([head | tail]) do
    # The kernel function IO to show the content of head
    IO.puts(head)

    # Calling the function itself
    # (where the recursion happens)
    # by passing the tail as the argument of the function
    show_each_one(tail)
  end

  # Creating the function using the pattern Matching
  # In the case of an empty list, it will return null (nil)
  def show_each_one([]), do: nil
end

# Creating a list
list = [1, :atom, 3, 4, "string"]
[1, :atom, 3, 4, "string"]


# Call the function Example.show_each_one/1
# by passing the list as argument
Example.show_each_one(list)

# It will return the result below:
1
atom
3
4
string
nil
Enter fullscreen mode Exit fullscreen mode

We could use many other kernel functions to work with the lists:

  • first(list) - To return the first element of the list.
  • last(list) - To return the list element of the list.
  • insert_at(list, index, value) - To insert one element in the list in a certain position.
  • And many others.

If you need to know more about the details of the List, I suggest you look at the Elixir documentation about the List.

Something interesting that we need to know is that the functions we use to work with a List use recursion in their implementation.

I hope that this content helps and makes sense to you! See ya!

Contacts:
Email: contato@diegonovais.com.br
LinkedIn: https://www.linkedin.com/in/diegonovais/
Github: https://github.com/dnovais
Twitter: https://twitter.com/diegonovaistech

Top comments (0)