ElixirSchoolの学習メモです。
基本
リスト内包表記はElixirで列挙体(enumerable)をループするための糖衣構文、短縮形のこと。
内包表記はEnum
やStream
を反復するためのより手軽な文を生成するためによく用いられる。
与えられた一つ以上のコレクションに対して、各要素の値のすべての組み合わせを展開して、
場合によって値をフィルタし、残った値で新しいコレクションを作成する。
内包表記の一般的な文法は次のとおり。
result = for generator or filter... [, into: value], do: expression
iex(2)> for x <- [1, 2, 3, 4, 5], do: x * x
[1, 4, 9, 16, 25]
入れ子になったループのように、複数のジェネレータを用いることも可能。
iex(6)> for x <- [1, 2], y <- [5, 6], do: x * y
[5, 6, 10, 12]
iex(8)> for x <- [1, 2], y <- [5, 6], do: {x, y}
[{1, 5}, {1, 6}, {2, 5}, {2, 6}]
内包表記はリストだけでなく、列挙可能なものならどんなものにも使える。
# マップ
iex(10)> for {k, v} <- %{"a" => "A", "b" => "B"}, do: {k, v}
[{"a", "A"}, {"b", "B"}]
# バイナリ
iex(11)> for <<c <- "hello">>, do: <<c>>
["h", "e", "l", "l", "o"]
ジェネレータは入力値セットと左辺の変数を比較するのにパターンマッチを使っている。
iex(13)> for {:ok, val} <- [ok: "Hello", error: "Unknown", ok: "World"], do: val
["Hello", "World"]
フィルタ
フィルタは内包表記のためのある種のガード。
フィルタされた値がfalse
かnil
を返す場合は最終的なリストから取り除かれる。
iex(4)> for x <- [1, 2, 3, 4, 5], x < 4, do: x * x
[1, 4, 9]
また、ジェネレータ同様複数のフィルタを使うこともできる。
:intoの使用
リストではなく、他のものを生成したい場合は:into
オプションを使う。
# キーワードリストからマップを作成する
iex(15)> for {k, v} <- [one: 1, two: 2, three: 3], into: %{}, do: {k, v}
%{one: 1, three: 3, two: 2}
ビット文字列は列挙可能なので、リスト内包表記と:into
を用いて文字列を作成することができる。
iex(16)> for c <- [72, 101, 108, 108, 111], into: "", do: <<c>>
"Hello"