👌
[Feature #20160] rescue keyword for case expressions
[Feature #20160] rescue keyword for case expressions
-
case ~ when
でrescue
節も含めるようにしたいという提案 - 例えば以下のよう
case ~ when
があるときに
case (parsed = parse(input))
when Integer then handle_int(parsed)
when Float then handle_float(parsed)
end
-
parse
の例外をキャッチしたい場合は以下のように記述する必要がある
begin
case (parsed = parse(input))
when Integer then handle_int(parsed)
when Float then handle_float(parsed)
# ...
end
rescue ParseError
# ...
end
- これを以下のよう記述したいという旨になる
case (parsed = parse(input))
when Integer then handle_int(parsed)
when Float then handle_float(parsed)
rescue ParseError
# ...
rescue ArgumentError
# ...
else
# ... fallthrough for all rescue and when cases
ensure
# ... called always
end
- 他にも以下のようなコードも例としてあげられています。おもしろい
parser = Parser.new(io)
loop do
case parser.parse # blocks for reading io in chunks
rescue StandardError => e
if parser.can_recover?(e)
# tolerate failure, ignore
next
else
emit_fail(e)
break
end
when :integer
emit_integer(parser.last)
when :float
emit_float(parser.last)
when :done
# e.g EOF reached, IO closed, YAML --- end of doc, XML top-level closed, whatever makes sense
emit_done
break
else
parser.rollback # e.g rewinds io, we may not have enough data
ensure
parser.checkpoint # e.g saves io position for rollback
end
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
# handle ParseError
in :error, ArgumentError => error
# handle ArgumentError
else
# all other cases — note that there is no assignment here
# but most parsing should probably be exhaustive
end
- 最終的には matz が『処理すべき例外の発生源について混乱する可能性がある』『(コメントに提示されていた)以下のコードの方が直感的でわかりやすい』ということで Reject されている
begin
parsed = parse(input)
rescue ParseError
# ...
end
case parsed
when Integer then handle_int(parsed)
when Float then handle_float(parsed)
# ...
end
Discussion