Understanding Tuples and Atoms in Elixir

In Elixir there is a data structure called Tuple. What a funky name.
There is also a data type called Atom.
Let’s go over what they are, how they’re used in Elixir and why they’re powerful.

Chapter 1: Tuples.

I was watching a video from José Valim at Pluralsight, and I heard him say that a function would return a Tuple.

I had never heard that word before.




It’s a funky name isn’t it ?

There is a weird sound to it.


Anyway he went on to show something really cool.
The function he was mentioning returned something like this:

{:ok, result}

Okay, I thought, that looks interesting.

It’s like you have this first piece which tells you if the outcome was good or bad: :ok, and then you get your so desired result.

Similarly, the function could otherwise return:

{:error, reason}

Damn, neat!
Isn’t it ?

But then… he said the first item was an atom.


What the hell is an atom ??

I mean, I know what an atom is, but I’m guessing this isn’t the kind that has electrons and neutrons.

Chapter 2: Atoms

I went to Elixir website:

Atoms are constants where their name is their own value. Some other languages call these symbols.

iex> :hello
iex> :hello == :world

The booleans true and false are, in fact, atoms:

iex> true == :true
iex> is_atom(false)
iex> is_boolean(:false)

Ah! Ok, so, atoms are like symbols. Symbols that carry a meaning.
And the Erlang virtual machine only keeps 1 copy of each atom in memory.

They are especially useful when used internally in your application but not necessarily printed.
So instead of saying your function went "ok" as a string, you say that it went :ok, as an atom.

This is probably natural for Rubists but me coming from Javaland it was totally alien.

A good property of an atom is that it is universal and equal even between different machines.
So an :ok will be equal to another :ok, even if they’re in different servers or Erlang nodes.

:ok, back to the tuples.

Back to Chapter 1: Tuplewares

So, now I get what :ok and :error are supposed to do there.
The first item on the tuple tells me what happened, and the second gives me the details.

But let’s talk about the tuples a little more.

What are Tuples?
Tuples are a collection of values.
They typically come in the size of 2 or 3 items, so, small, not your collection to store life stories and your bank statement, but more of like summary information.

The way I showed you, is one of the most common ways it is used in Elixir.

{:status_atom, your_stuff}

And what do functional programmers do ?

That’s right.

We Pattern Match!!

Case and Pattern Matching with Tuples

Let’s talk briefly about case in Elixir. By the way check out my Pattern Matching post if you haven’t yet.

case number do
	1 -> IO.puts "Number one"
	2 -> IO.puts "Number two"
	_ -> IO.puts "Something other than one or two"

This is how we use case in Elixir.
You put a expresion, variable or function call right after the case, and put options to control the flow of the program.

When number is equal to 1, the program will print "Number one". Likewise, when it is 2, "Number two" will be printed.
Anything else will get you the "Something other than one or two" option.

Note that the _ matches to anything, and the underscore itself denotes that we don’t intend to use this value at all.
We don’t care about the value in this case.

Now, say we have this function: your_function(argument), and we know it returns a tuple.

Typically we could do:

case your_function(argument) do
	{:ok,  result} ->
		# do successful stuff
	{:error, reason} ->
		# do erroneous stuff

What this means is:

  1. Call your_function passing the parameter argument.
  2. Analyse the result returned by your_function(argument)
  3. Choose whether the result looks like {:ok, something} or {:error, reason}
  4. Follow the appropriate course of actions, based on the previous assessment.

That’s beautiful.

You avoid putting a lot of boilerplate code to support straight forward use cases.
And also very complicated ones actually.

However, this is not the only way tuples are used.
Another example would be something like the Ecto.update_all/3.

This function returns a tuple also, but it’s a little different.
This function is updating several rows ina a database, so what the return tuple gives is {rows_affected, output}, and if there is no output, it simply comes nil.

So if you updated there and you updated 57 rows, and the database returned no output, it would give you this:

{57, nil}

Again, loyal.
Properly saluted!


So that’s my brief memoir of Tuples and Atoms.
Hope you enjoyed, don’t forget to share this post with your friends.

And until next time, Take care and happy brewing,