## Lists

A list is either the empty list, written as `Nil`

,
or a cons cell, written as `x :: xs`

where `x`

is
the head element and `xs`

is the tail of the list.
The `List`

type is polymorphic so you can have a
list of integers, written as `List[Int32]`

, or a
list of strings written as `List[String]`

.

We write the empty list as follows:

```
Nil
```

We can construct a list of strings with the strings
`"Hello"`

and `"World"`

as follows:

```
"Hello" :: "World" :: Nil
```

Given a list there are many useful operations we can perform on it.

For example, we can compute the length of a list as follows:

```
List.length(1 :: 2 :: 3 :: Nil)
```

We can also reverse the order of elements in a list:

```
List.reverse(1 :: 2 :: 3 :: Nil)
```

We can append two lists using the `List.append`

function as follows:

```
let xs = (1 :: 2 :: 3 :: Nil);
let ys = (4 :: 5 :: 6 :: Nil);
List.append(xs, ys)
```

Or, alternatively, we can use the built-in append
operator `:::`

as follows:

```
let xs = (1 :: 2 :: 3 :: Nil);
let ys = (4 :: 5 :: 6 :: Nil);
xs ::: ys
```

Flix has an extensive collection of functions to operate on lists.

Here are some of the most common:

```
List.count(x -> x == 1, 1 :: 2 :: 3 :: Nil);
List.filter(x -> x == 1, 1 :: 2 :: 3 :: Nil);
List.map(x -> x + 1, 1 :: 2 :: 3 :: Nil);
List.foldLeft((x, y) -> x + y, 0, 1 :: 2 :: 3 :: Nil)
```

And here are some more exotic functions:

```
List.intersperse("X", "a" :: "b" :: "c" :: Nil)
```

which inserts `"X"`

between every element in the
list.

```
let l1 = "X" :: "Y" :: Nil;
let l2 = ("a" :: "b" :: Nil) :: ("c" :: "d" :: Nil) :: Nil;
List.intercalate(l1, l2)
```

which inserts the list `l1`

between every element in
the list `l2`

.

We can write our own recursive functions to operate on lists.

For example, here is an implementation of the `map`

function:

```
///
/// Returns the result of applying `f` to every element in `l`.
/// That is, the result is of the form: `f(x1) :: f(x2) :: ...`.
///
pub def map(f: a -> b \ ef, l: List[a]): List[b] \ ef = match l {
case Nil => Nil
case x :: xs => f(x) :: map(f, xs)
}
```