リストもタプルも、ともに複数のデータの容れ物です。値の型は問わず、いくつでも要素として納められます(「Elixir入門 02: 型の基本」参照)。
iex> list = [3.14, :pie, true, "Apple"]
[3.14, :pie, true, "Apple"]
iex> tuple = {3.14, :pie, true, "Apple"}
{3.14, :pie, true, "Apple"}
けれど、ふたつの仕組みは異なり、したがって使い途も変わります。ふたつの違いとしては、つぎのような点が挙げられます。
違い | タプル | リスト |
---|---|---|
サイズ | 固定 | 可変 |
要素の操作 | 原則としてしない |
List のほかEnum の関数が使える |
データの参照 | 速い | 遅くなることがある |
リストの仕組み
リストは「連結リスト」です。要素は値とつぎの要素への参照をもちます。要素を特定するインデックスは備えません。
タプルの仕組み
タプルは、連番インデックスをもった静的なデータ構造です。インデックス順に、まとめてメモリに納められます。
サイズに関わる違い
リストは要素を加えたり、除いたりすることが自由です。その数とそれぞれのデータによって、リストのサイズは変わります。タプルは、要素をまとめて納めたときに、サイズが決まります。要素の追加や削除は、実際上行われません。
サイズを得る関数は、リストがlength/1
、タプルはtuple_size/1
です。つぎのような処理の違いがあります。
関数 | 値の求め方 | 処理 |
---|---|---|
length/1 | 数えて返す | 遅い |
tuple_size/1 | あらかじめ計算されている | 速い |
要素の追加や削除などの操作
リストはList
のほかEnum
モジュールの豊富な関数で操作できます。特定の要素を追加したり、削除したり、変更するだけでなく、すべての要素を取り出して処理できるのです。
タプルを操作するTuple
モジュールの関数は多くありません。要素を操作したいときには、リストを使うことが推奨されています。要素を加えたり、書き替えたりする場合は、メモリに新たなタプルをつくることになるので、負荷が高くなってしまうからです。
To manipulate a collection of elements, use a list instead.
(「Tuple」より)
データの参照と取り出し
リストにはインデックスがなく、要素間の参照をたどることで値が取り出されます。つまり、最後の要素を参照するには、すべての要素を順にたどらなければならないということです。もっとも、すべての要素を列挙して処理するには差し支えなく、Enum
モジュールの関数が使えます。
タプルの要素は、elem/2
関数により、インデックスを与えてただちに取り出せます。ただし、Enum
モジュールの関数は使えません。
iex> tuple = {:ok, "hello"}
{:ok, "hello"}
iex> elem(tuple, 1)
"hello"
適した使い途
リストは、要素を自由に操作でき、メモリの許すかぎり加えられます。タプルは、予め決まったデータのやり取りに向くでしょう。
データを操作したり、数が変わったり、とくに多くの数のデータを扱うにはリストが使われます。1件のデータの複数の属性値を表すときは、タプルが適しているでしょう。典型は、キーと値の組みです。関数の戻り値によく用いられます。たとえば、File.read/1
は、ファイル読み込みの結果と内容をタプルで返します。
iex> File.read("path/to/existing/file")
{:ok, "... ファイルの中身 ..."}
iex> File.read("path/to/unknown/file")
{:error, :enoent}
また、タプルはパターンマッチングにも用いられます。
iex> tuple = {:ok, :example}
{:ok, :example}
iex> {:ok, atom} = tuple
{:ok, :example}
iex> atom
:example
属性の数が増えてくると、タプルよりマップの方がわかりやすいかもしれません。
iex> {100, 150, 50}
{100, 150, 50}
iex> %{x: 100, y: 150, z: 50}
%{x: 100, y: 150, z: 50}
リストとタプルを組み合わせることもできます。キーワードリストがまさにその例です(「Elixir入門 07: キーワードリストとマップ」参照)。
iex> point = [x: 100, y: 150, z: 50]
[x: 100, y: 150, z: 50]
iex> point == [{:x, 100}, {:y, 150}, {:z, 50}]
true
まとめ
- リストもタプルも任意の型のデータを複数納められます。
- リストとタプルの仕組みは異なるので、つぎの点で違いがあります。
- サイズ
- 要素の操作
- データの参照
- リストとタプルそれぞれの性質にあった使い途があります。
- リスト: 要素を操作し、数が変わるデータ
- タプル: 複数の属性をもった固定データ