# Tuples and Named Tuples

#### Tuples in Julia are fixed-length collections of values, of potentially different data types, which can't be modified once initialized. Tuples are closely related to function arguments.

## Initializing Tuples

Tuples can be created in a similar way 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.

Tuples in general can’t be modified one initialized. For example, attempting to do:

`t[1] = 2*t[1]`

will result in the following `ERROR: MethodError: no method matching setindex!(::Tuple{Float64, Float64}, ::Float64, ::Int64)`

.

However, this doesn’t mean we can’t operate with tuples. Tuples can be copied, converted to arrays, and more.

For example, we can overwrite the value of a tuple with another tuple:

`t = (2*t[1], t[2])`

This also allows us to apply a broadcasting operation, like what we can do with arrays:

`t = t .* 2`

## 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
```

## 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.

## 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.