DEV Community

Masatoshi Nishiguchi
Masatoshi Nishiguchi

Posted on

Elixirでリストの最初の要素を取得

ElixirでListの最初の要素を取得する方法についていくつか考えてみました。一見初歩中の初歩のように見えますが、実は複数のやり方があり、その使い分けがエンジニアとしての腕の見せどころにもなりえます。

これからElixirを始める方にはこのサイトがおすすめです。

https://elixir-lang.info/

Elixirとコミュニティの雰囲気をゆるく味わいたい方は「先端ピアちゃん」さんの動画が超オススメです。

https://www.youtube.com/@piacerex

ElixirのList

Listは値の集合です。複数の異なるタイプを含むことができます。一意でない値を含むこともできます。

ひとつ注意点は、ElixirList連結リストとして実装されていることです。今回の実験では特に問題がないですが、他の主要プログラミング言語の配列とは異なるので思い込みは禁物です。

https://elixirschool.com/ja/lessons/basics/collections

https://qiita.com/search?q=Elixir+List

実験の準備

実験用List

要素数の異なるパターンのリストを用意します。

lists = [
  [],
  [nil],
  [1],
  [1, 2],
  [1, 2, 3],
]
Enter fullscreen mode Exit fullscreen mode

実験を実行する関数

  • 前項で作成したリストを何度も使用するので、共通部分を切り出し関数化します。
  • 万一、例外が発生した場合にもテストを止めず、エラー内容を値として処理します。
test_fun = fn do_test ->
  for list <- lists do
    try do
      do_test.(list)
    rescue
      e -> inspect(e)
    end
  end
end
Enter fullscreen mode Exit fullscreen mode

Kernel.hd/1 (hd/1)

hd/1Listが空の時にはエラーになります。

test_fun.(fn list ->
  hd(list)
end)
Enter fullscreen mode Exit fullscreen mode
["%ArgumentError{message: \"errors were found at the given arguments:\\n\\n  * 1st argument: not a nonempty list\\n\"}",
 nil,
 1,
 1,
 1]
Enter fullscreen mode Exit fullscreen mode

https://hexdocs.pm/elixir/Kernel.html#hd/1

List.first/1

List.first/2のユニークなところは、空リストの最初の要素はnilと解釈する点です。この特性が便利な場面があります。

test_fun.(fn list ->
  List.first(list)
end)
Enter fullscreen mode Exit fullscreen mode
[nil,
 nil,
 1,
 1,
 1]
Enter fullscreen mode Exit fullscreen mode

https://hexdocs.pm/elixir/List.html#first/2

Enum.at/2

@torifukukaiou さんからお便りをいただき、これを見落としていたのに気がつきました。ありがとうございます。

Enum.at/2List.first/2と同様に空リストの最初の要素をnilとします。

test_fun.(fn list ->
  Enum.at(list, 0)
end)
Enter fullscreen mode Exit fullscreen mode
[nil,
 nil,
 1,
 1,
 1]
Enter fullscreen mode Exit fullscreen mode

Enum.fetch/2

Enum.fetch/2は空リストの最初の要素を探すことを異常とみなしますが、プログラマーが例外処理しやすいように{:ok, any} | :errorを出力してくれます。

test_fun.(fn list ->
  Enum.fetch(list, 0)
end)
Enter fullscreen mode Exit fullscreen mode
[:error,
 {:ok, nil},
 {:ok, 1},
 {:ok, 1},
 {:ok, 1}]
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode
["%Enum.OutOfBoundsError{message: \"out of bounds error\"}",
 nil
 1,
 1,
 1]
Enter fullscreen mode Exit fullscreen mode

https://hexdocs.pm/elixir/Enum.html#fetch!/2

[first | _rest]でパターンマッチ

このパターンは最初の要素と残り全部の2つに分割されます。Listが空の時はエラーになります。要素が一個の時は大丈夫のようです。

test_fun.(fn list ->
  [first | _rest] = list
  first
end)
Enter fullscreen mode Exit fullscreen mode
["%MatchError{term: []}",
 nil,
 1,
 1,
 1]
Enter fullscreen mode Exit fullscreen mode

https://elixirschool.com/ja/lessons/basics/pattern_matching

[first, _, _]でパターンマッチ

このパターンの場合は、要素数がピッタリ一致する場合のみヨシとされます。

test_fun.(fn list ->
  [first, _, _] = list
  first
end)
Enter fullscreen mode Exit fullscreen mode
["%MatchError{term: []}",
 "%MatchError{term: [nil]}",
 "%MatchError{term: [1]}",
 "%MatchError{term: [1, 2]}",
 1]
Enter fullscreen mode Exit fullscreen mode

ElixirのEnum技

List等の集合を操作する時に使うEnumには無数の興味深い関数やテクニックがありますが、ここではいくつか特にイーやつをご紹介させて頂こうと思います。

https://qiita.com/torifukukaiou/items/e07ed758d1259d14a2b7

https://qiita.com/torifukukaiou/items/3b65e5c04fa8c55f526e

https://qiita.com/torifukukaiou/items/4481f7884a20ab4b1bea

Top comments (0)