🌟
[Feature #21359] Exception#cause の値を Exception#cause= で制御できるようにする提案
[Feature #21359] Introduce Exception#cause=
for Post-Initialization Assignment
-
Exception#cause
を利用する『より内側で発生した例外』を取得することができる
begin
begin
raise "inner"
rescue
raise "outer"
end
rescue => e
p e # => #<RuntimeError: outer>
p e.cause # => #<RuntimeError: inner>
end
- この
cause
はraise
の引数として制御することもできる
begin
# ここで設定した例外が Exception#cause から参照できる
raise "outer", cause: RuntimeError.new("inner")
rescue => e
p e # => #<RuntimeError: outer>
p e.cause # => #<RuntimeError: inner>
end
- この
#cause
の値をException#cause=
で制御できるようにする提案
cause = RuntimeError.new("low-level error")
error = StandardError.new("higher-level error")
error.cause = cause
- 明示的に
cause
を指定したケースってどういうときなんですかね?ライブラリの内部とかで使われたりするのかな - 以下のような実装イメージも書かれていますねー
- 逆にこれを使えば現状でも同様の機能は実装できるんですねーはえ〜
error = StandardError.new("error")
cause = RuntimeError.new("cause")
class Exception
def cause= value
backtrace = self.backtrace_locations
raise self, cause: value
rescue Exception
self.set_backtrace(backtrace)
end
end
p error.cause # nil
error.cause = cause
p error.cause # => #<RuntimeError: cause>
-
Exception#cause=
の追加は matz は反対していますね - また別の代替案として
Exception.new("message", cause: cause)
のように#initialize
で指定できるようにする案も提示されていますがこれはこれですべてのサブクラスでサポートするのがむずかしいみたいですねえ
Discussion