😊
【bugs.ruby Advent Calender】case ~ when で rescue 句も含めるようにする提案【9日目】
bugs.ruby Advent Calender 9日目の記事です。
これはなに
今年1年間通してみてきた bugs.ruby のチケットの中から気になったものを1つずつ取り上げていく Advent Calender です。
取り上げるチケットは基本的にこのブログで取り上げたものになります。
記事のまとめは ここを参照 してください。
[Feature #20160] rescue keyword for case expressions
case ~ when
で発生した例外を次のような rescue
句で受け取ることができようにする提案です。
case (parsed = parse(input))
when Integer
handle_int(parsed)
when Float
handle_float(parsed)
else
# when に該当しなかった場合
rescue ParseError
# ParseError が発生した場合
rescue ArgumentError
# ArgumentError が発生した場合
ensure
# ... すべてのケースから呼び出される
end
要は case ~ when
と begin ~ rescue ~ end
を1つの式で表現できるようにする提案ですね。
現状だと次のように記述する必要があります。
begin
case (parsed = parse(input))
when Integer
handle_int(parsed)
when Float
handle_float(parsed)
else
# ...
end
rescue ParseError
# ...
end
この提案自体は『処理すべき例外の発生源について混乱する可能性がある』『(コメントに提示されていた)以下のコードの方が直感的でわかりやすい』ということで Reject されていますねー。
結局は例外の処理がどこにかかっているのかが case
なのかどの when
なのかわからない、みたいな感じですかねー。
なので次のように『例外が発生する可能性がある箇所ごと』に rescue
するほうがわかりやすいとのこと。
# parse で例外が発生しうるのであればこっちで rescue する
begin
parsed = parse(input)
rescue ParseError
# ...
end
case parsed
when Integer
handle_int(parsed)
when Float
handle_float(parsed)
end
ちなみにコメントでは以下のようなパターンマッチを利用するコードも提示されていますね。
def parse(input)
# parsing logic
rescue StandardError => e
[:error, e]
end
case parse(input)
in Integer => parsed_int
handle_int(parsed_int)
in Float => parsed_float
handle_float(parsed_float)
in :error, ParseError => error
# ParseError の場合
in :error, ArgumentError => error
# ArgumentError の場合
else
# どれにも該当しない場合
end
こういうのは好き
Discussion