# Tuples, Lists, Sets

Apart from complex data types such as `maps`

and `records`

, LIGO also
features `tuples`

, `lists`

and `sets`

.

## Tuples

Tuples gather a given number of values in a specific order and those
values, called *components*, can be retrieved by their index
(position). Probably the most common tuple is the *pair*. For
example, if we were storing coordinates on a two dimensional grid we
might use a pair `[x, y]`

to store the coordinates `x`

and `y`

. There
is a *specific order*, so `[y, x]`

is not equal to `[x, y]`

in
general. The number of components is part of the type of a tuple, so,
for example, we cannot add an extra component to a pair and obtain a
triple of the same type: `[x, y]`

has always a different type from
`[x, y, z]`

, whereas `[y, x]`

might have the same type as `[x, y]`

.

### Defining Tuples

Unlike a record, tuple types do not
have to be defined before they can be used. However below we will give
them names by *type aliasing*.

### Destructuring

If we want to get the first and last name of the `full_name`

type, we can use
destructuring. Destructuring a tuple allows you to give names to the elements
inside the tuple.

This also works in functions:

note: the underscore to indicate that we ignore the last element of the tuple.

and within a code block:

note: nested patterns in record destructuring are not yet available

### Accessing Components

Accessing the components of a tuple in OCaml is achieved by
pattern matching. LIGO
currently supports tuple patterns only in the parameters of functions,
not in pattern matching. However, we can access components by their
position in their tuple, which cannot be done in OCaml. *Tuple
components are zero-indexed*, that is, the first component has index
`0`

.

## Lists

Lists are linear collections of elements of the same type. Linear
means that, in order to reach an element in a list, we must visit all
the elements before (sequential access). Elements can be repeated, as
only their order in the collection matters. The first element is
called the *head*, and the sub-list after the head is called the
*tail*. For those familiar with algorithmic data structure, you can
think of a list a *stack*, where the top is written on the left.

💡 Lists are needed when returning operations from a smart contract's main function.

### Defining Lists

### Adding to Lists

Lists can be augmented by adding an element before the head (or, in
terms of stack, by *pushing an element on top*). This operation is
usually called *consing* in functional languages.

In JsLIGO, the *cons operator* is infix and noted `, ...`

. It is
not symmetric: on the left lies the element to cons, and, on the
right, a list on which to cons.

### Accessing list elements

You cannot access element directly in list but you can access the
first element, the head or the rest of the list, the tail. The two
function to access those are `List.head_opt`

and `List.tail_opt`

However, the canonical way to destructure lists is using pattern matching.

### Functional Iteration over Lists

A *functional iterator* is a function that traverses a data structure
and calls in turn a given function over the elements of that structure
to compute some value. Another approach is possible in JsLIGO:
*loops* (see the relevant section).

There are three kinds of functional iterations over LIGO lists: the
*iterated operation*, the *map operation* (not to be confused with the
*map data structure*) and the *fold operation*.

#### Iterated Operation over Lists

The first, the *iterated operation*, is an iteration over the list
with a unit return value. It is useful to enforce certain invariants
on the element of a list, or fail.

For example you might want to check that each value inside of a list
is within a certain range, and fail otherwise. The predefined
functional iterator implementing the iterated operation over lists is
called `List.iter`

.

In the following example, a list is iterated to check that all its
elements (integers) are strictly greater than `3`

.

#### Mapped Operation over Lists

We may want to change all the elements of a given list by applying to
them a function. This is called a *map operation*, not to be confused
with the map data structure. The predefined functional iterator
implementing the mapped operation over lists is called `List.map`

and
is used as follows.

#### Folded Operation over Lists

A *folded operation* is the most general of iterations. The folded
function takes two arguments: an *accumulator* and the structure
*element* at hand, with which it then produces a new accumulator. This
enables having a partial result that becomes complete when the
traversal of the data structure is over. Folding can be done in two
ways, labelled with the directions left and right. One way to tell them
apart is to look where the folded function, and the fold itself, keep
the accumulator in their signatures. Take for example a function `f`

,
a list `[1; 2; 3; 4; 5]`

, and an accumulator that's just an empty
list. A rough approximation of the result of a left fold would look
like `f(f(f(f(f([], 1), 2), 3), 4), 5)`

, while a right fold would
instead look like `f(1, f(2, f(3, f(4, f(5, [])))))`

.

The left fold operation has a function signature of
`List.fold_left (a -> x -> a) -> a -> x list -> a`

, while the right
fold operation has `List.fold_right (x -> a -> a) -> x list -> a -> a`

.
Here is an example of their use.

## Sets

Sets are unordered collections of values of the same type, like lists
are ordered collections. Like the mathematical sets and lists, sets
can be empty and, if not, elements of sets in LIGO are *unique*,
whereas they can be repeated in a *list*.

### Empty Sets

In JsLIGO, the empty set is denoted by the predefined value
`Set.empty`

.

### Non-empty Sets

In JsLIGO, you can define a non-empty set using the `Set.literal`

function
which takes a list of elements & returns a set.

You can check that `2`

is not repeated in `my_set`

by using the LIGO
compiler like this (the output will sort the elements of the set, but
that order is not significant for the compiler):

### Adding an element to a Set

You can add an element to a set, using `Set.add`

function.

### Set Membership

In JsLIGO, the predefined predicate `Set.mem`

tests for membership
in a set as follows:

### Cardinal of Sets

The predefined function `Set.size`

returns the number of
elements in a given set as follows.

### Updating Sets

There are two ways to update a set, that is to add or remove from it.

In JsLIGO, we can use the predefined functions `Set.add`

and
`Set.remove`

. We update a given set by creating another one, with or
without some elements.

### Functional Iteration over Sets

A *functional iterator* is a function that traverses a data structure
and calls in turn a given function over the elements of that structure
to compute some value. Another approach is possible in JsLIGO:
*loops* (see the relevant section).

There are three kinds of functional iterations over LIGO maps: the
*iterated operation*, the *mapped operation* (not to be confused with
the *map data structure*) and the *folded operation*.

#### Iterated Operation

The first, the *iterated operation*, is an iteration over the map with
no return value: its only use is to produce side-effects. This can be
useful if for example you would like to check that each value inside
of a map is within a certain range, and fail with an error otherwise.

The predefined functional iterator implementing the iterated operation
over sets is called `Set.iter`

. In the following example, a set is
iterated to check that all its elements (integers) are greater than
`3`

.

#### Folded Operation

A *folded operation* is the most general of iterations. The folded
function takes two arguments: an *accumulator* and the structure
*element* at hand, with which it then produces a new accumulator. This
enables having a partial result that becomes complete when the
traversal of the data structure is over.

The predefined fold over sets is called `Set.fold`

, however an
additional function, `Set.fold_right`

, has been added with the
signature ```
val fold_right : ('acc * 'elt -> 'acc) * 'elt set * 'acc ->
'acc
```

.