ElixirでListの最初の要素を取得する方法についていくつか考えてみました。一見初歩中の初歩のように見えますが、実は複数のやり方があり、その使い分けがエンジニアとしての腕の見せどころにもなりえます。
これからElixirを始める方にはこのサイトがおすすめです。
Elixirとコミュニティの雰囲気をゆるく味わいたい方は「先端ピアちゃん」さんの動画が超オススメです。
https://www.youtube.com/@piacerex
ElixirのList
Listは値の集合です。複数の異なるタイプを含むことができます。一意でない値を含むこともできます。
ひとつ注意点は、ElixirのListは連結リストとして実装されていることです。今回の実験では特に問題がないですが、他の主要プログラミング言語の配列とは異なるので思い込みは禁物です。
https://elixirschool.com/ja/lessons/basics/collections
https://qiita.com/search?q=Elixir+List
実験の準備
実験用List
要素数の異なるパターンのリストを用意します。
lists = [ [], [nil], [1], [1, 2], [1, 2, 3], ] 実験を実行する関数
- 前項で作成したリストを何度も使用するので、共通部分を切り出し関数化します。
- 万一、例外が発生した場合にもテストを止めず、エラー内容を値として処理します。
test_fun = fn do_test -> for list <- lists do try do do_test.(list) rescue e -> inspect(e) end end end Kernel.hd/1 (hd/1)
test_fun.(fn list -> hd(list) end) ["%ArgumentError{message: \"errors were found at the given arguments:\\n\\n * 1st argument: not a nonempty list\\n\"}", nil, 1, 1, 1] https://hexdocs.pm/elixir/Kernel.html#hd/1
List.first/1
List.first/2のユニークなところは、空リストの最初の要素はnilと解釈する点です。この特性が便利な場面があります。
test_fun.(fn list -> List.first(list) end) [nil, nil, 1, 1, 1] https://hexdocs.pm/elixir/List.html#first/2
Enum.at/2
@torifukukaiou さんからお便りをいただき、これを見落としていたのに気がつきました。ありがとうございます。
Enum.at/2はList.first/2と同様に空リストの最初の要素をnilとします。
test_fun.(fn list -> Enum.at(list, 0) end) [nil, nil, 1, 1, 1] Enum.fetch/2
Enum.fetch/2は空リストの最初の要素を探すことを異常とみなしますが、プログラマーが例外処理しやすいように{:ok, any} | :errorを出力してくれます。
test_fun.(fn list -> Enum.fetch(list, 0) end) [:error, {:ok, nil}, {:ok, 1}, {:ok, 1}, {:ok, 1}] https://hexdocs.pm/elixir/Enum.html#fetch/2
Enum.fetch!/2
Enum.fetch!/2は空リストの最初の要素を探すことを異常とみなし、エラーを起こします。hd/1の時と結果が同じです。エラーメッセージはhd/1の方が具体的でわかりやすような気がしますが、こっちのエラーの方がスッキリ簡潔です。ここは好みが別れるところかもしれません。
test_fun.(fn list -> Enum.fetch!(list, 0) end) ["%Enum.OutOfBoundsError{message: \"out of bounds error\"}", nil 1, 1, 1] https://hexdocs.pm/elixir/Enum.html#fetch!/2
[first | _rest]でパターンマッチ
このパターンは最初の要素と残り全部の2つに分割されます。Listが空の時はエラーになります。要素が一個の時は大丈夫のようです。
test_fun.(fn list -> [first | _rest] = list first end) ["%MatchError{term: []}", nil, 1, 1, 1] https://elixirschool.com/ja/lessons/basics/pattern_matching
[first, _, _]でパターンマッチ
このパターンの場合は、要素数がピッタリ一致する場合のみヨシとされます。
test_fun.(fn list -> [first, _, _] = list first end) ["%MatchError{term: []}", "%MatchError{term: [nil]}", "%MatchError{term: [1]}", "%MatchError{term: [1, 2]}", 1] ElixirのEnum技
List等の集合を操作する時に使うEnumには無数の興味深い関数やテクニックがありますが、ここではいくつか特にイーやつをご紹介させて頂こうと思います。
https://qiita.com/torifukukaiou/items/e07ed758d1259d14a2b7
Top comments (0)