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.