配列は、Elixirで値の集まりを保持するための基本的なデータ型です。配列は_イミュータブル_で、変更することはできません。配列を変更する操作は、どれも新しい配列を返します。配列はEnumerableプロトコルを実装しているので、EnumモジュールやStreamモジュールの関数を利用できます。
Elixirの配列は、連続したメモリ領域を持つ配列ではなく、連結リストとして実装されています。そのため、配列の要素にアクセスするには、配列の長さに応じた線形時間がかかります。
配列は、リテラル形式、ヘッドテール記法(cons演算子の|を使います)、またはその両方を組み合わせて書くことができます。
# Literal Form
[]
[1]
[1, 2, 3]
# Head-tail Notation
[]
# same as [1]
[1 | []]
# same as [1, 2, 3]
[1 | [2 | [3 | []]]]
# Mixed
# same as [1, 2, 3]
[1 | [2, 3]]
cons(|)演算子の前に、複数の要素を書くこともできます。
# Multiple prepends
[1, 2, 3 | [4, 5]]
ヘッドテール記法を使うと、配列に要素を追加できます。
list = [2, 1]
[3, 2, 1] == [3 | list]
# => true
繰り返しの中で配列に要素を末尾追加するのは、アンチパターンとされています。要素を末尾に追加するには配列全体をたどって最後に足す必要があるため、繰り返しのたびに新しい要素を末尾に追加すると、毎回配列全体をたどることになります。
同じ結果は、逆順にした配列の先頭に要素を追加してから、その結果を逆順にすることで得られます。先頭への追加は高速な操作で、定数時間で済みます。
# Appending to the end of a list (potentially slow)
[1, 2, 3] ++ [4] ++ [5] ++ [6]
# Prepend to the start of a list (faster, due to the nature of linked lists)
[6 | [5 | [4 | [3, 2, 1]]]]
# then reverse!
配列でよく使うKernel関数には、次のようなものがあります。
hd/1は配列の_ヘッド_、つまり_最初_の要素を返します。tl/1は配列の_テール_、つまり_最初_の要素を除いた配列を返します。length/1は配列の要素数を返します。in/2は、その要素が配列に含まれているかどうかを示す真偽値を返します。Listモジュールもあります。
配列にはどんなデータ型でも入れられ、異なるデータ型を混ぜて入れることもできます。
list = [1, :a, 2.0, "string"]