natewallis

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

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

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

11
Post #4
aseigo

aseigo

To pile in on this one :slight_smile:

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!

10
Post #8
tcoopman

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

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.

Where Next?

Popular in Discussions Top

jesse
Hi everyone, I hesitated to post this here because I don’t want you to think I’m spamming, but I’ve been working on a Platform-as-a-Serv...
New
AlexMcConnell
The reason that Rails is as popular as it is is because it’s very easy for relatively inexperienced developers to get a lot of work done....
588 20142 166
New
joeerl
I’m playing with Elixir - It’s fun. I think @rvirding does give Elixir courses these days. Re: files and database - when I given Erlang ...
New
New
opsb
We’re considering our architecture from a viewpoint of scaling our traffic heavily over the next 6 months. Our current deployment is runn...
New
RudManusachi
What configs will make sense to put to runtime.exs? – A bit of how I configure apps: I have generic configs in config/config.exs, dev...
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New

Other popular topics Top

JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
AstonJ
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New

We're in Beta

About us Mission Statement