👌

[Feature #20160] rescue keyword for case expressions

2024/02/14に公開

[Feature #20160] rescue keyword for case expressions

  • case ~ whenrescue 節も含めるようにしたいという提案
  • 例えば以下のよう 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 されている
case (parsed = parse(input))
rescue ParseError
  # ...
rescue ArgumentError
  # ...
when Integer then handle_int(parsed)
when Float then handle_float(parsed)
  ...
else
  # ...
ensure
  # ...
end
GitHubで編集を提案

Discussion