LoginSignup
4
0

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

Last updated at Posted at 2023-08-16

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

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

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

ElixirのList

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

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

実験の準備

実験用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)

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

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

List.first/1

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

実験2
test_fun.(fn list ->
  List.first(list)
end)
結果2
[nil,
 nil,
 1,
 1,
 1]

Enum.at/2

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

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

実験3
test_fun.(fn list ->
  Enum.at(list, 0)
end)
結果3
[nil,
 nil,
 1,
 1,
 1]

Enum.fetch/2

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

実験4
test_fun.(fn list ->
  Enum.fetch(list, 0)
end)
結果4
[:error,
 {:ok, nil},
 {:ok, 1},
 {:ok, 1},
 {:ok, 1}]

Enum.fetch!/2

Enum.fetch!/2は空リストの最初の要素を探すことを異常とみなし、エラーを起こします。hd/1の時と結果が同じです。エラーメッセージはhd/1の方が具体的でわかりやすような気がしますが、こっちのエラーの方がスッキリ簡潔です。ここは好みが別れるところかもしれません。

実験5
test_fun.(fn list ->
  Enum.fetch!(list, 0)
end)
結果5
["%Enum.OutOfBoundsError{message: \"out of bounds error\"}",
 nil
 1,
 1,
 1]

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

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

実験6
test_fun.(fn list ->
  [first | _rest] = list
  first
end)
結果6
["%MatchError{term: []}",
 nil,
 1,
 1,
 1]

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

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

実験7
test_fun.(fn list ->
  [first, _, _] = list
  first
end)
結果7
["%MatchError{term: []}",
 "%MatchError{term: [nil]}",
 "%MatchError{term: [1]}",
 "%MatchError{term: [1, 2]}",
 1]

ElixirのEnum技

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

4
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0