エラーハンドリング構文と言えば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が使われているのか気を付けてください。
参考文献
コメントを送る
コメントはブログオーナーのみ閲覧できます