Tuple
Here are a few key points about the tuple data type.
- A tuple is a collection type. It is a structure that contains a fixed number of things.
- A tuple’s elements are ordered and fixed in size.
- A tuple does NOT mean TWO. Tuples can have many elements. However, it is common to see a tuple with only two elements.
- A common usage in Elixir is to return multiple result values from a function in a tuple.
The following example represent common function return values. Each tuple contains 2 pieces of information or data.
{:ok, result}
{:error, reason}
The first piece of information is an atom (ie: :ok
or :error
) that tells if the operation succeeded or not. If we got an :ok
, we know it succeeded and the next piece of data is the result of the operation. If we got the atom :error
then we know the operation failed and the reason
may tell us why.
Another example of using a tuple to return multiple pieces of information at once might be the result of a function that splits a list of integers into odd and even sets. Imagine that a function named split_odd_even/1
is available to us. This function leaves the original list unmodified (immutable) and returns the two different result sets through a tuple. It could look like this:
{odd_results, even_results} = split_odd_even([1, 2, 7, 12, 15])
odd_results
#=> [1, 7, 15]
even_results
#=> [2, 12]
Here is another tuple example that contains multiple pieces of data. In this example the tuple contains a person’s name and age:
{"Howard", 32}
Using the Kernel.elem/2 function, you can extract the value of an element from a tuple.
tuple = {:foo, :bar, 3}
elem(tuple, 1)
#=> :bar
elem({:foo, :bar}, 2)
#=> ** (ArgumentError) argument error
A cleaner and more natural way to do this is with “pattern matching” which isn’t covered here.
You can replace an element using Kernel.put_elem/3. Remember, Elixir isn’t changing the tuple, internally it is creating a new tuple where the elements point back to the previous tuple’s values, with the exception of the new change.
tuple = {:foo, :bar, 3}
put_elem(tuple, 2, :baz)
#=> {:foo, :bar, :baz}
You can see that the original tuple
variable has not been modified:
tuple
#=> {:foo, :bar, 3}
Tuples are best for a fixed number of elements. If you need a dynamic container that preserves order, use a List
instead.