Elixir-errors-handling
Elixir-エラー処理
Elixirには、エラー、スロー、終了の3つのエラーメカニズムがあります。 各メカニズムを詳細に調べてみましょう。
エラー
エラー(または例外)は、コードで例外的なことが発生したときに使用されます。 サンプルエラーは、文字列に数字を追加しようとすることで取得できます-
IO.puts(1 + "Hello")
上記のプログラムを実行すると、次のエラーが生成されます-
** (ArithmeticError) bad argument in arithmetic expression
:erlang.+(1, "Hello")
これはサンプルの組み込みエラーでした。
エラーを発生させる
raise関数を使用してエラーを raise できます。 同じことを理解するための例を考えてみましょう-
#Runtime Error with just a message
raise "oops" # * *(RuntimeError) oops
他のエラーはraise/2でエラー名とキーワード引数のリストを渡すことで発生する可能性があります
#Other error type with a message
raise ArgumentError, message: "invalid argument foo"
また、独自のエラーを定義して発生させることもできます。 次の例を考慮してください-
defmodule MyError do
defexception message: "default message"
end
raise MyError # Raises error with default message
raise MyError, message: "custom message" # Raises error with custom message
エラーの救済
プログラムを突然終了させたくないのですが、エラーを注意深く処理する必要があります。 このために、エラー処理を使用します。* try/rescue *コンストラクトを使用して、エラーを*レスキュー*します。 同じことを理解するために、次の例を考えてみましょう-
err = try do
raise "oops"
rescue
e in RuntimeError -> e
end
IO.puts(err.message)
上記のプログラムが実行されると、次の結果が生成されます-
oops
パターンマッチングを使用して、rescueステートメントのエラーを処理しました。 エラーを使用せず、単に識別目的で使用する場合は、フォームを使用することもできます-
err = try do
1 + "Hello"
rescue
RuntimeError -> "You've got a runtime error!"
ArithmeticError -> "You've got a Argument error!"
end
IO.puts(err)
上記のプログラムを実行すると、次の結果が生成されます-
You've got a Argument error!
注-Elixir標準ライブラリのほとんどの関数は2回実装されます。1回はタプルを返し、もう1回はエラーを発生させます。 たとえば、 File.read および* File.read!*関数。 最初のファイルは、ファイルが正常に読み取られた場合にタプルを返し、エラーが発生した場合は、このタプルを使用してエラーの理由を示しました。 エラーが発生した場合は、2番目のエラーが発生しました。
最初の関数アプローチを使用する場合、エラーに一致するパターンのケースを使用し、それに応じてアクションを実行する必要があります。 2番目のケースでは、エラーを起こしやすいコードに対してtry rescueアプローチを使用し、それに応じてエラーを処理します。
投げる
Elixirでは、値をスローして後でキャッチできます。 スローとキャッチは、スローとキャッチを使用しない限り値を取得できない状況のために予約されています。
インスタンスは、ライブラリとインターフェイスする場合を除いて、実際には非常にまれです。 たとえば、Enumモジュールが値を見つけるためのAPIを提供していないこと、および数値のリストで13の最初の倍数を見つける必要があると仮定します。
val = try do
Enum.each 20..100, fn(x) ->
if rem(x, 13) == 0, do: throw(x)
end
"Got nothing"
catch
x -> "Got #{x}"
end
IO.puts(val)
上記のプログラムが実行されると、次の結果が生成されます-
Got 26
Exit
プロセスが「自然な原因」(たとえば、未処理の例外)で終了すると、終了シグナルを送信します。 プロセスは、終了シグナルを明示的に送信することによって停止することもできます。 私たちは次の例を考えてみましょう-
spawn_link fn -> exit(1) end
上記の例では、値1の終了シグナルを送信することにより、リンクされたプロセスが停止しました。 try/catchを使用してexitを「キャッチ」することもできます。 たとえば-
val = try do
exit "I am exiting"
catch
:exit, _ -> "not really"
end
IO.puts(val)
上記のプログラムが実行されると、次の結果が生成されます-
not really
後に
場合によっては、エラーを発生させる可能性のある何らかのアクションの後にリソースをクリーンアップする必要があります。 try/afterコンストラクトを使用すると、これを実行できます。 たとえば、何か問題が発生した場合でも、ファイルを開き、after句を使用してファイルを閉じることができます。
{:ok, file} = File.open "sample", [:utf8, :write]
try do
IO.write file, "olá"
raise "oops, something went wrong"
after
File.close(file)
end
このプログラムを実行すると、エラーが発生します。 ただし、 after ステートメントは、そのようなイベントが発生したときにファイル記述子が閉じられるようにします。