😽
[Bug #21123] Proc#curry を #instance_exec に渡したときのバグ報告
[Bug #21123] instance_exec with curried proc
-
#instance_exec / instance_eval
にブロックを渡した場合、そのブロックのself
は#instance_exec
のレシーバになる
a = Object.new
def a.foo(n)
n + n
end
a.instance_exec {
# self は a になる
pp self # => #<Object:0x00007d08416b6748>
# なので foo もレシーバなしで呼び出すことができる
pp foo(4) # => 8
}
- この
#instance_exec / instance_eval
にProc#curry
したオブジェクトを渡すとエラーになるというバグ報告
a = Object.new
def a.foo(n)
n + n
end
body = proc { |n|
# self が a であることを期待するが main になる
pp self # => main
# なので foo メソッドを呼び出すことができずにエラーになる
pp foo(n) # => error: undefined method 'foo' for main (NoMethodError)
}
a.instance_exec(2, &body.curry)
- これなんですが期待する挙動になっており
Proc#curry
はラッパーしたProc
を返すので次のようなコードと同じになります
a = Object.new
def a.foo(n)
p
end
body = proc { |n| foo(n) }
# body2 のブロック内の self が a になる
# body は関節的に body2 から呼び出されているので instance_exec とは関連性がない
body2 = proc { |n|
pp self # => #<Object:0x00007f9a840b6618>
body.call(n)
}
a.instance_exec(0, &body2)
- 内部的な話はありつつ
Proc#curry
でもinstance_exec
が反映される方が自然なんですかねー
Discussion