エラーハンドリング構文と言えばJavaScriptではtry~catch
, Rubyではbegin~rescue
, Pythonではtry~except
があります。
そう、多くの言語でエラーハンドリング構文は1つです。しかしElixirには2種類のエラーハンドリング構文があります(!?)。
それはタイトルにもある通りtry~catch
とtry~rescue
です。
このエントリでは2種類のエラーハンドリング構文try~catch
とtry~rescue
にどんな違いがあるのか説明します。
Elixirでは前提としてexample/1
というメソッドは{:ok, result}
か{:error, reason}
を返すように設計します。
case example(foo) do
{:ok, result} -> # do_something
{:error, reason} -> # do_something
end
戻り値としてエラーを返すのはGoに似ていますね。
result だけを返すかエラーを発生させるメソッドはメソッド名の末尾に!
を付けて定義します。
result = example!(foo)
example!/1
がエラーを発生させた場合、エラーをキャッチしなければプログラムは終了します。
ではエラーをキャッチするにはtry~catch
とtry~rescue
のどちらを使えば良いでしょうか?
そのためにはまずElixirにおける2つのエラー発生方法を知る必要があります。
Elixirではエラーを発生させる方法としてthrow/1
とraise
があります。
throw/1
は、ある値を投げ、キャッチするために使います。が、あまり使うことはないようです。
実際には新しいElixirコードでこれらを使うのは非常にまれです
throw/1
で投げた値はtry~catch
で捕捉することができます。
try do
throw(1)
catch
x -> "Caught: #{x}"
end
またtry~catch
ではexit
も捕捉できます。
通常、明示的にエラーを発生させたいときはraise/1
やraise/2
を使います。
raise "Oh no!"
raise ArgumentError, message: "the argument value is invalid"
raise
で発生させたエラーや、その他のランタイムエラーはtry~rescue
を使って捕捉することができます。
try do
do_something!(foo)
rescue
e in ArgumentError -> IO.puts("the argument value is invalid")
e -> IO.puts("error: " <> inspect(e))
end
またRubyのensure
, Pythonのfinally
に相当するafter
句もあります。
このエントリではElixirのエラーハンドリング構文try~catch
とtry~rescue
の違いを説明しました。
私はその違いを理解しないまま本番にコードを反映してしまって...というのをやったことがあります。
外部ライブラリを使う際などは、中でthrow/1
が使われているのか、raise
が使われているのか気を付けてください。
参考文献
コメントを送る
コメントはブログオーナーのみ閲覧できます