😽

[Bug #21123] Proc#curry を #instance_exec に渡したときのバグ報告

2025/02/08に公開

[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_evalProc#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)
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 が反映される方が自然なんですかねー
GitHubで編集を提案

Discussion