Enumerables
- ElixirはEnumerablesなデータを処理するのにEnumモジュールを提供している
- EnumはListやMapなど異なるデータ型を扱うように設計されている
- なのでデータによって特有の操作、例えばListの特定の位置に要素を追加したいというような場合はListモジュールのinsert_at/3を使う必要がある。
# Listの各要素を * 2 する
iex> Enum.map([1, 2, 3], fn x -> x * 2 end)
[2, 4, 6]
# mapの各要素を key * value する
iex> Enum.map(%{1 => 2, 3 => 4}, fn {k, v} -> k * v end)
[2, 12]
# List内の要素の合計を出す
iex> Enum.reduce(1..3, 0, &+/2)
6
The pipe operator
- |> で関数の呼び出し結果をつなげることができる。左辺の関数の実行結果を右辺の第一引数として渡す。
# List内の各要素を3倍して、その中から奇数の合計を求める処理
# |> を使わないで書いた場合
iex> Enum.sum(Enum.filter(Enum.map(1..100, &(&1 * 3)), &(rem(&1, 2) != 0)))
7500
# |> を使って書いた場合
iex> 1..100 |> Enum.map(&(&1 * 3)) |> Enum.filter(&(rem(&1, 2) != 0)) |> Enum.sum
7500
# |> を使うとListに対してやりたいことが宣言的に書けてみやすい。
Streams
- Enumの代わりに遅延評価をサポートするStreamモジュールが提供されている
1..100 |> Stream.map(&(&1 * 3)) |> Stream.filter(&(rem(&1, 2) != 0)) |> Enum.sum
- Streamモジュールの多くの関数はenumerableな引数を受け付け、Streamを返す
- 使い方によっては無限列のStreamを返す
# [1,2,3]のサイクルが続くStreamを束縛。この時点でのstreamは1,2,3を繰り返すStream
stream = Stream.cycle([1, 2, 3])
# take で streamから必要な個数を取り出す時点で初めてstreamの関数が評価される
iex> Enum.take(stream, 10)
[1, 2, 3, 1, 2, 3, 1, 2, 3, 1]
- 遅延評価が有効 = 必要になった際に初めて評価されて展開されるので巨大なデータを扱うことに向いている。