リストに要素をひとつ加える場合の書き方です。
リストはヘッドとテイルの組みで表される
リストは|
演算子を用いて、頭の要素(ヘッド)と残りのリスト(テイル)に分けることができます。
iex> [head | tail] = [1, 2, 3]
[1, 2, 3]
iex> head
1
iex> tail
[2, 3]
これは、Elixirにおけるリストの内部的な扱いを表しています。つまり、リストはヘッドとテイルの組みを入れ子にしたものです。最後のテイルは空のリスト[]
であることにご注目ください。
iex> [1 | [2 | [3 | []]]]
[1, 2, 3]
最後のテイルが空[]
でないと、不適切なリストとして扱われます。ただし、特別な環境で使われるため、エラーにはなりません(「List」参照)。
iex> [1 | [2 | [3 | 4]]]
[1, 2, 3 | 4]
リストのはじめに要素を加える
リスト同士を連結するのは++/2
演算子です。要素(item
)をリスト(list
)のはじめに加える処理は、つぎのように書けます。
[item] ++ list
正しいコードです。けれど、つぎのように内部表現に沿って|
演算子を用いる方がよいでしょう。
[item | list]
リストの最後に要素を加える
要素を最後に加えるときは、++/2
演算子の出番に思われます。
list ++ [item]
動作に問題はありません。もっとも、最後のリスト要素を見つけなければならないので、サイズが大きいほど効率は落ちます。公式ドキュメントの++/2
の解説によれば、はじめに加えて、順序を逆転させる方がよいそうです。
[item |list] |> Enum.reverse()
Erlangによる実装
++/2
の実装は:erlang.++/2
(lists.append/2
)を呼び出しています。Erlangの処理はつぎのとおりで、再帰のたびに左辺のリストのコピーがつくられるのです(5「List Handling」5.1「Creating a List」参照)。
append([H|T], Tail) ->
[H|append(T, Tail)];
append([], Tail) ->
Tail.
Enum.reverse/1
の実装が呼び出すErlangの:lists.reverse/1
は、反転したリストを新たにひとつつくるだけです。前出5.1「Creating a List」の例を実測した記事「Erlang 入門 (3) - リスト」によると、処理時間に約30倍の開きが出たといいます。