29
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

gumi Inc.Advent Calendar 2018

Day 3

Elixir: リストとタプルはいつどちらを使うのか

Last updated at Posted at 2018-12-05

リストもタプルも、ともに複数のデータの容れ物です。値の型は問わず、いくつでも要素として納められます(「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の関数が使える
データの参照 速い 遅くなることがある

リストの仕組み

リストは「連結リスト」です。要素は値とつぎの要素への参照をもちます。要素を特定するインデックスは備えません。

qiita_12_001_001.png

タプルの仕組み

タプルは、連番インデックスをもった静的なデータ構造です。インデックス順に、まとめてメモリに納められます。

qiita_12_001_002.png

サイズに関わる違い

リストは要素を加えたり、除いたりすることが自由です。その数とそれぞれのデータによって、リストのサイズは変わります。タプルは、要素をまとめて納めたときに、サイズが決まります。要素の追加や削除は、実際上行われません。

サイズを得る関数は、リストが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

まとめ

  • リストもタプルも任意の型のデータを複数納められます。
  • リストとタプルの仕組みは異なるので、つぎの点で違いがあります。
    • サイズ
    • 要素の操作
    • データの参照
  • リストとタプルそれぞれの性質にあった使い途があります。
    • リスト: 要素を操作し、数が変わるデータ
    • タプル: 複数の属性をもった固定データ
29
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?