natewallis
Why do tuples exist?
Hi,
I have recently started devoting some more time to learning Elixir and a question that always nags me is why do tuples exist in Elixir? Is it purely because they are a side effect of erlang and therefore had to be brought across?
Whether to use a tuple or a list feels like a bit of a grey area to me.
Where do people draw the line when it comes to deciding on whether to use a tuple or a list?
Thanks,
Nate
First Post!
derek-zhou
Older functional language such as Lisp do not have tuples. So they are not strictly speaking necessary. However, they make certain ideas clearer, certain operations cheaper, so most modern languages, functional or not, tend to have it.
As for where to draw the line, just look at elixir’s core library. Ask yourself why a tuple is used instead of a list anywhere you see it. Eventually you will have the idea.
Most Liked
mpope
Tuples have an advantage over lists because they’re stored contiguously. They have better ‘spatial locality’. Caching benefits from two types of locality, ‘temporal’ which is reusing a specific part of memory, or ‘spatial’ locality, which is the ability to load a segment of data into a CPU cache / RAM and have fast access to parts of that data because they’re close together. Tuples help with the later. Lists potentially require more random memory access.
Due to these characteristics, tuples are comparatively fast to read and create but slow to modify. More detailed information can be found here: Client Challenge
aseigo
To pile in on this one ![]()
Tuples are: strictly positional (you won’t be moving their contents around, nor will you be referencing the contents by keys, and pattern matches must be exact), are not Enumerable (so you won’t get to use the Enum module), relatively space efficient (caveats apply) and fast for random access (due to positional nature). Various mutations are provided in the Tuple module.
Maps are: fast lookups, good update performance, values have lookup keys, they are Enumerable, and pattern matches are quite free-form due to the key’d values
Lists are: Enumerable, suited to collections of items, poor for random access at large sizes, but good for iterating and modifying. The swiss-army-knife data bag of Elixir, and often more than fast-enough in most cases.
Keyword lists are: Lists of 2-Tuples!
As Keyword lists show, these can all be mixed and matched: tuples as the values (or keys!) of maps, maps as the values in a list, lists as elements in tuples .. algebraic types ftw!
tcoopman
This blog from @sasajuric is also a great resource. Comparing some different data structures in different scenarios. Seems like tuples definitely have their place in some use cases
Last Post!
Will-W
While they look a lot like them, tuples are not an alternative to lists, they are an alternative to structs.
The usecase for tuples and structs is to group together several values that belong together, e.g. because they’re different attributes of the same thing. You know in advance how many attributes there are, and what they mean.
A list is for a collection of things that are the same ‘shape’. Usually they’re the same type - i.e. all integers, or all the same type of struct, or all functions. If they’re different types then they’re still expected to be handled in the same way. If you have “some number of things that are all similar but I don’t know how many in advance” then you want a list, e.g. if you’re reading in a file and you separate it into each line, then you would use a list (of strings).
To go back to tuples and structs, the classic ‘person’ example in so many code examples is good here. For our purposes a person has two attributes - name (a string) and age (a number). Here is how to return each of the options from a function:
As a tuple:
def func() do
{"John", 33}
end
As a struct:
defmodule Person do
defstruct [:name, :age]
end
def func() do
%Person{name: "John", age: 33}
end
The tuple is easiest: you don’t have to declare anything in advance you just create it. Users of this function then have to know (e.g. through documentation or convention) that the first element is the name, and the second element is the age. They also get unwieldy when you’ve got more than a few elements - you end up with difficult to read code accessing elements. Adding an extra parameter also usually required touching a lot of code Tuples are excellent for pairing up 2 or 3 things together, and passing them around locally (e.g. internal to a module), or where there is a good convention (e.g. the {:error, message} return convention).
For anything more complicated than a couple of elements you want a struct - rather than having to know which position is which member the fields are named. Structs enforce that you haven’t forgotten any of the members, allow you to add new members without affecting most code and provide more information to autocomplete and type checking (also pattern matching if you want). Structs are a great choice a lot of the time.
You could also use a map for this purpose, but you usually don’t want to. A map is closer to a list in that it’s a collection of an unknown number of items, but rather than looking them up by position in an array, you look them up by name. Structs are actually implemented ‘under the hood’ as maps, but to use them in the way I’m talking about above you want the guarantees that structs provide. For example, when using a struct you can guarantee that a given field in the struct is present (because Elixir ensures that), whereas with a map you would always have to check in case you were passed a malformed one.
Popular in Discussions
Other popular topics
Chat & Discussions>Discussions
Latest on Elixir Forum
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex









