We'll continue learning about the functions in the `Kernel` module. Today, we're going to learn about the functions related to lists, tuples, and maps. I do not know why all these functions are in the `Kernel` module rather than the `List`, `Tuple`, and `Map` modules, but I can make some guesses.

A couple functions correspond to operators, so I can see why they are located in the `Kernel` module. Some can also be used in guard clauses, so I can see why they would be in the `Kernel` module. Some don't fall in either category, so I have no idea why they are located in the `Kernel` module. There's certainly a reason, but I'm not aware of what that reason is.

## List Functions

These are functions in the `Kernel` module that operate on lists.

### Kernel.++/2

The `Kernel.++/2` function corresponds to the list concatenation operator `++`, which we already discussed back when I covered lists. I'll give a few examples here.

``````iex> [3] ++ ["a", "z"]
[3, "a", "z"]
iex> [1, 2, 3] ++ []
[1, 2, 3]
iex> [1, 2, 3] ++ [["a", "j"], [3.14]]
[1, 2, 3, ["a", "j"], [3.14]]
``````

### Kernel.++/2

The `Kernel.--/2` function corresponds to the list difference (subtraction) operator `--`, which we already discussed back when I covered lists. I'll give a few examples here.

``````iex> [1, 2, 3] -- [3, 4, 5]
[1, 2]
iex> [1, 2, 3] -- [5, 6, 7]
[1, 2, 3]
iex> [1, 2, 3] -- []
[1, 2, 3]
iex> [1, 2, 3] -- [1, 2, 3, 4, 5]
[]
``````

### Kernel.destructure/2

The `Kernel.destructure/2` function destructures a list. It works a lot like pattern matching for lists, but it's a bit more forgiving if the list does not exactly match the pattern. If there are extra variables in the destructuring expression, those will be filled with `nil` values.

The first parameter of the function contains an expression just like you'd see on the left-hand side of an `=` operator. The second parameter is a list. It returns a list containing the destructured values.

Here are some examples.

``````iex> destructure([a, b, c], [1, 2, 3])
[1, 2, 3]
iex> a
1
iex> b
2
iex> c
3
iex> destructure([first, second], [1, 2, 3, 4, 5])
[1, 2]
iex> first
1
iex> second
2
iex> {first, second}
{1, 2}
iex> destructure([a, b, c], [1, 2])
[1, 2, nil]
iex> destructure([a, b, c], [])
[nil, nil, nil]
iex> {a, b}
{nil, nil}
iex> destructure([a, 4, 5], [3, 4, 5])
[3, 4, 5]
iex> a
3
iex> destructure([a, 4, 5], [4, 5, 6])
** (MatchError) no match of right hand side value: [4, 5, 6]

``````

It will attempt to match the pattern, and if it receives a partial match where the number of items differ, it will do the best it can to destructure the list, and will do so without an error. If the pattern just doesn't match at all, like in the last example, it will throw an error.

### Kernel.hd/1

We've seen the `Kernel.hd/1` function before while learning about lists. All it does is return the element at the head of the list. If the list is empty, there is no head, so it will throw an error.

This function can be used in guard clauses.

``````iex> hd([1, 2, 3])
1
iex> hd([10, -4, 34])
10
iex> hd([])
** (ArgumentError) argument error
:erlang.hd([])
iex> hd(["a"])
"a"
``````

### Kernel.length/1

The `Kernel.length/1` function just returns the length of a list. It can be used in guard clauses.

``````iex> length([4, 5, 6, 7, 9])
5
iex> length([-2, 3])
2
iex> length([:ok])
1
iex> length([])
0
``````

### Kernel.tl/1

The `Kernel.tl/1` function returns the tail of a list. This is everything except the element that is the head of the list. If the list is empty, there is no tail, so it will throw an error.

This function can be used in guard clauses.

``````iex> tl([-1, 0, 1, 2, -4])
[0, 1, 2, -4]
iex> tl(["a", "b", "c"])
["b", "c"]
iex> tl([4])
[]
iex> tl([])
** (ArgumentError) argument error
:erlang.tl([])
``````

## Tuple Functions

These are functions in the `Kernel` module that operate on tuples.

### Kernel.elem/2

The `Kernel.elem/2` function returns the element in a tuple that is found at the specified index. If a tuple does not have an element at that index, the function throws an error.

This function can be used in a guard clause.

``````iex> elem({"Bob", "Spud", "Blub"}, 2)
"Blub"
iex> elem({"Bob", "Spud", "Blub"}, 0)
"Bob"
iex> elem({"Bob", "Spud", "Blub"}, 5)
** (ArgumentError) argument error
:erlang.element(6, {"Bob", "Spud", "Blub"})
iex> elem({"Bob", "Spud", "Blub"}, -1)
** (ArgumentError) argument error
:erlang.element(0, {"Bob", "Spud", "Blub"})
``````

It looks like negative indexes are not recognized in this function like they are in some other functions like the ones in the `Enum` module.

### Kernel.put_elem/3

The `Kernel.put_elem/3` function updates the element at the specified index in a tuple. If If a tuple does not have an element at that index, the function throws an error.

``````iex> put_elem({1, 2, 3}, 1, "Nero")
{1, "Nero", 3}
iex> put_elem({1, 2, 3}, 0, "Nero")
{"Nero", 2, 3}
iex> put_elem({1, 2, 3}, 4, "Nero")
** (ArgumentError) argument error
:erlang.setelement(5, {1, 2, 3}, "Nero")
iex> put_elem({}, 0, 1)
** (ArgumentError) argument error
:erlang.setelement(1, {}, 1)
``````

### Kernel.tuple_size/1

The `Kernel.tuple_size/1` function returns the size of a tuple. This function can be used in guard clauses.

``````iex> tuple_size({1, 2, 3})
3
iex> tuple_size({1, 2, 3, "a", "b", "c"})
6
iex> tuple_size({5})
1
iex> tuple_size({})
0
``````

## Map Functions

These are functions in the `Kernel` module that operate on maps.

### Kernel.map_size/1

The `Kernel.map_size/1` returns the size of a map. This function can be used in guard clauses.

``````iex> map_size(%{name: "Bob", age: 35})
2
iex> map_size(%{name: "Bob"})
1
iex> map_size(%{})
0
``````

## Continuing with the Kernel Module

I'll stop here for today. The next time we come back to the `Kernel` module, I'll cover functions related to binaries and numbers.