Tuples and Named Tuples

by Martin D. Maas, Ph.D

Tuples in Julia are collections of values of possibly different data types, which can't be modified once initialized. Tuples are mostly good for small fixed-length collections, and are closely related to function arguments.

Initializing Tuples

Tuples can be created similarly to arrays, replacing square brackets with parenthesis. For example,

t = (3.14, 2.72)

Creates a variable with type Tuple{Float64, Float64}, whose values can be accessed via t[1] and t[2].

In fact, we don’t even need the parenthesis to initialize a tuple, and simply doing

t = 3.14, 2.72

will work just as well.

Destructuring Tuples

We can cast the elements of a tuple as different variables in a very straightforward manner:

pi_approx, e_approx = t

Tuples are, for this reason, a convenient return type for a function that seemingly returns multiple outputs, such as we discussed in the post about functions.

Converting Tuples to Arrays

Tuples can be converted to arrays in various ways: using the collect function, array comprehensions, or the splat notation.

a = (1, 2, 3)

t1 = collect(a);
t2 = [x for x in a];
t3 = [a...];           

all producing the same output:

3-element Vector{Int64}:
 1
 2
 3

Named Tuples

An interesting variant is that we can assign names to the different elements of a tuple. For example, by declaring

p = ( x = 1.1, y = 2.4)

The elements of p can be accessed via p.x and p.y as well as p[1] and p[2].

p is of type NamedTuple{(:x, :y), Tuple{Float64, Float64}}.

We can also retrieve the names of the keys and the values of a named tuple, using the keys and values functions, as follows:

K = keys(p)                 # (:x, :y)
V = values(p)               # (1.1, 2.4)

and we can merge this key/value pairs into a named tuple again with the zip function:

p_new = (; zip(K,V)...)     # (x = 1.1, y = 2.4)

Merging Named Tuples

An other interesting operation we can do with Named Tuples is to merge them.

For example, let’s say that we have some parameters defined in a Named Tuple:

TemporalParams = ( 
    Δt = 0.1, 
    T = 2
)

and we then compute some extra quantity which we then would like to pack together into a similar tuple, we can then do

SpatialParams = ( 
    Δx = 0.05, 
    a = 0,
    b = 100
)

TotalParams = merge(TemporalParams, SpatialParams)

Destructuring Named Tuples

Since Julia 1.7, there is a new sytnax that can be used to destructure a NamedTuple:

(; y, x) = p

So, let’s say that we have passed the complete list of parameters to a certain function, but we only want to use a few of them, we can then do something like

(; a,b,Δt ) = TotalParams

This will create new symbols a,b,and Δt, without the need to constantly reference them like TotalParams.a,TotalParams.b,TotalParams.Δt.

Also note that the parameters can be destructured regardless of their order.

This is a very cool feature I personally use a lot to deal with different kinds of parameters.