## Lists

Lists are simple collections of values which may include multiple types; lists may also include non-unique values:

``````iex> [3.14, :pie, "Apple"]
[3.14, :pie, "Apple"]``````

Elixir implements list collections as linked lists. This means that accessing the list length is an operation that will run in linear time (`O(n)`). For this reason, it is typically faster to prepend than to append:

``````iex> list = [3.14, :pie, "Apple"]
[3.14, :pie, "Apple"]
# Prepending (fast)
iex> ["π" | list]
["π", 3.14, :pie, "Apple"]
# Appending (slow)
iex> list ++ ["Cherry"]
[3.14, :pie, "Apple", "Cherry"]``````

### List Concatenation

List concatenation uses the `++/2` operator:

``````iex> [1, 2] ++ [3, 4, 1]
[1, 2, 3, 4, 1]``````

A side note about the name (`++/2`) format used above: In Elixir (and Erlang, upon which Elixir is built), a function or operator name has two components: the name you give it (here `++`) and its arity. Arity is a core part of speaking about Elixir (and Erlang) code. It is the number of arguments a given function takes (two, in this case). Arity and the given name are combined with a slash. We’ll talk more about this later; this knowledge will help you understand the notation for now.

### List Subtraction

Support for subtraction is provided via the `--/2` operator; it’s safe to subtract a missing value:

``````iex> ["foo", :bar, 42] -- [42, "bar"]
["foo", :bar]``````

Be mindful of duplicate values. For every element on the right, the first occurrence of it gets removed from the left:

``````iex> [1,2,2,3,2,3] -- [1,2,3,2]
[2, 3]``````

Note: List subtraction uses strict comparison to match the values. For example:

``````iex> [2] -- [2.0]
[2]
iex> [2.0] -- [2.0]
[]``````

When using lists, it is common to work with a list’s head and tail. The head is the list’s first element, while the tail is a list containing the remaining elements. Elixir provides two helpful functions, `hd` and `tl`, for working with these parts:

``````iex> hd [3.14, :pie, "Apple"]
3.14
iex> tl [3.14, :pie, "Apple"]
[:pie, "Apple"]``````

In addition to the aforementioned functions, you can use pattern matching and the cons operator `|` to split a list into head and tail. We’ll learn more about this pattern in later lessons:

``````iex> [head | tail] = [3.14, :pie, "Apple"]
[3.14, :pie, "Apple"]
3.14
iex> tail
[:pie, "Apple"]``````

## Tuples

Tuples are similar to lists, but are stored contiguously in memory. This makes accessing their length fast but modification expensive; the new tuple must be copied entirely to memory. Tuples are defined with curly braces:

``````iex> {3.14, :pie, "Apple"}
{3.14, :pie, "Apple"}``````

It is common for tuples to be used as a mechanism to return additional information from functions; the usefulness of this will be more apparent when we get into pattern matching:

``````iex> File.read("path/to/existing/file")
{:ok, "... contents ..."}
{:error, :enoent}``````

## Keyword lists

Keyword lists and maps are the associative collections of Elixir. In Elixir, a keyword list is a special list of two-element tuples whose first element is an atom; they share performance with lists:

``````iex> [foo: "bar", hello: "world"]
[foo: "bar", hello: "world"]
iex> [{:foo, "bar"}, {:hello, "world"}]
[foo: "bar", hello: "world"]``````

The three characteristics of keyword lists highlight their importance:

• Keys are atoms.
• Keys are ordered.
• Keys do not have to be unique.

For these reasons, keyword lists are most commonly used to pass options to functions.

## Maps

In Elixir, maps are the “go-to” key-value store. Unlike keyword lists, they allow keys of any type and are un-ordered. You can define a map with the `%{}` syntax:

``````iex> map = %{:foo => "bar", "hello" => :world}
%{:foo => "bar", "hello" => :world}
iex> map[:foo]
"bar"
iex> map["hello"]
:world``````

As of Elixir 1.2, variables are allowed as map keys:

``````iex> key = "hello"
"hello"
iex> %{key => "world"}
%{"hello" => "world"}``````

If a duplicate is added to a map, it will replace the former value:

``````iex> %{:foo => "bar", :foo => "hello world"}
%{foo: "hello world"}``````

As we can see from the output above, there is a special syntax for maps containing only atom keys:

``````iex> %{foo: "bar", hello: "world"}
%{foo: "bar", hello: "world"}
iex> %{foo: "bar", hello: "world"} == %{:foo => "bar", :hello => "world"}
true``````

In addition, there is a special syntax you can use with atom keys:

``````iex> map = %{foo: "bar", hello: "world"}
%{foo: "bar", hello: "world"}
iex> map.hello
"world"``````

Another interesting property of maps is that they provide their own syntax for updates (note: this creates a new map):

``````iex> map = %{foo: "bar", hello: "world"}
%{foo: "bar", hello: "world"}
iex> %{map | foo: "baz"}
%{foo: "baz", hello: "world"}``````

Note: this syntax only works for updating a key that already exists in the map! If the key does not exist, a `KeyError` will be raised.

To create a new key, instead use `Map.put/3`

``````iex> map = %{hello: "world"}
%{hello: "world"}
iex> %{map | foo: "baz"}