Enum
は列挙型(enumerable)データを扱うモジュールです。Enum
の関数はさまざまな列挙可能なデータ型に使える多態性をもちます。扱うデータはEnumerable
プロトコルを実装していればよいのです(「Elixir入門 10: EnumとStream」参照)。それらの関数の中から、値を探す3つの関数をご紹介します。とくに、Enum.find_value/3
については、公式ドキュメントよりわかりやすいコード例を示しました。
Enum.find/3
Enum.find/3
は、第3引数fun
の戻り値がtrue
と評価される最初の要素を返します。関数が引数に受け取るのは、取り出される各要素です。
find(enumerable, default \\ nil, fun)
find(t(), default(), (element() -> any())) :: element() | default()
第2引数はデフォルト値です。省くとnil
が与えられます。
iex> Enum.find([1, 2, 3], fn x -> rem(x, 2) == 0 end)
2
iex> Enum.find([1, 2, 3], fn x -> rem(x, 4) == 0 end)
nil
iex> Enum.find([1, 2, 3], 0, fn x -> rem(x, 4) == 0 end)
0
Enum.find_index/2
Enum.find_index/2
は、第2引数fun
の戻り値がtrue
と評価される最初の要素のインデックスを返します。関数が引数に受け取るのは、取り出される各要素です。
find_index(enumerable, fun)
find_index(t(), (element() -> any())) :: non_neg_integer() | nil
インデックスは0から始まる連番整数です。いずれの要素も、第2引数の関数fun
がtrue
と評価される値を返さないときはnil
となります。
iex> Enum.find_index([1, 2, 3], fn x -> rem(x, 2) == 0 end)
1
iex> Enum.find_index([1, 2, 3], fn x -> rem(x, 4) == 0 end)
nil
Enum.find_value/3
Enum.find_value/3
は、第3引数fun
の戻り値がtrue
と評価される最初の要素について、戻り値そのものを返します。関数が引数に受け取るのは、取り出される各要素です。
find_value(enumerable, default \\ nil, fun)
find_value(t(), any(), (element() -> any())) :: any() | nil
第2引数はデフォルト値です。省くとnil
が与えられます。
iex> Enum.find_value([1, 2, 3], fn x -> rem(x, 2) == 0 end)
true
iex> Enum.find_value([1, 2, 3], fn x -> rem(x, 4) == 0 end)
nil
iex> Enum.find_value([1, 2, 3], &is_number/1)
true
iex> Enum.find_value([1, 2, 3], "no bools!", &is_boolean/1)
"no bools!"
iex> Enum.find_value([1, 2, 3], fn x ->
...> case rem(x, 2) do
...> 0 -> {:even, x}
...> _ -> false
...> end
...> end)
{:even, 2}
公式ドキュメントのEnum.find_value/3
の項には、使い途の浮かぶ例が掲げられていないようです。たとえば、つぎのようにキーワードリストから値を取り出すことが考えられます。
iex> profile = [{company: "gumi, inc"}, {headquarters: "tokyo/japan"}]
iex> Enum.find_value(profile, fn {key, value} ->
...> case key do
...> :headquarters -> value
...> _ -> false
...> end
...> end)
"tokyo/japan"
この例は、and/2
を用いるともっと短く書けます。
iex> Enum.find_value(profile, fn {key, value} -> key == :headquarters and value end)
"tokyo/japan"