Elixir
Elixir Basics - 3. Tuples
Updated:
Tuples in Elixir, like lists, can hold any value. They are created with curly brackets {}
.
iex(1)> {"Hello", :true, 5.43}
{"Hello", true, 5.43}
Tuples vs Lists
However, unlike lists, the elements within a tuple are stored contiguously in memory. This means that you can access an element within a tuple via its index.
iex(2)> tuple = {"Hello", :true, 5.43}
{"Hello", true, 5.43}
iex(3)> elem(tuple, 2)
5.43
This also means that getting the size of a tuple is an inexpensive operation. Whereas with lists, it is an expensive operation.
iex(4)> tuple = {"Hello", :true, 5.43}
{"Hello", true, 5.43}
iex(5)> tuple_size(tuple)
3
Since lists are not stored continugously in memory, getting the size of a list is an expensive operation as the entire list chain has to be traversed, one element at a time, until the last element is found.
Adding Elements
Elements can be added to a tuple at a particular index by using the put_elem/3
function.
iex(6)> tuple = {"Hello", :true, 5.43}
{"Hello", true, 5.43}
iex(7)> put_elem(tuple, 2, 14)
{"Hello", true, 14}
Remember, that what is returned is a new tuple, the original tuple has not been modified because Elixir has immutable data structures.
iex(6)> tuple = {"Hello", :true, 5.43}
{"Hello", true, 5.43}
iex(7)> put_elem(tuple, 2, 14)
{"Hello", true, 14}
iex(8)> tuple
{"Hello", true, 5.43}
Common Use Cases
Tuples are often used in Elixir to return extra information from functions. For example, when using the File.read/1
function a tuple is returned where the first element is an atom letting you know if the operation was successful or not.
- If it is, the first element will be the atom
:ok
and then the contents of the file. - If not, the first element will be the atom
:error
and then the reason for the error.
iex(10)> h File.read/1
Returns {:ok, binary}, where binary is a binary data object that contains the
contents of path, or {:error, reason} if an error occurs.
Typical error reasons:
• :enoent - the file does not exist
• :eacces - missing permission for reading the file, or for searching
one of the parent directories
• :eisdir - the named file is a directory
• :enotdir - a component of the file name is not a directory; on some
platforms, :enoent is returned instead
• :enomem - there is not enough memory for the contents of the file
Length vs Size
In Elixir when counting elements within a data structure, the language differentiates between length
and size
. A function is named:
size
when the value is pre-calculated, like with Tuples, orlength
when the operation is linear like with Lists.
This means that getting the size
of a data structure is an inexpensive operation while getting the length
of a data structure is an expensive operation.
Size
For example, getting the size
of a Tuple is an inexpensive operation.
iex(4)> tuple = {"Hello", :true, 5.43}
{"Hello", true, 5.43}
iex(5)> tuple_size(tuple)
3
Remember, the reason this is inexpensive is because the size of the Tuple is already known since the elements are stored contiguiously in memory.
Length
Getting the length
of a List an expensive operation.
iex(12)> list = ["Hello", :true, 5.43]
["Hello", true, 5.43]
iex(13)> length(list)
3
Remember, the reason this is expensive is because the elements are not stored contiguiously in memory. The more elements there are in the list, the more expensive this operation becomes.