包含模块时 __callee__ 的意外值 – 这是 Ruby 错误吗?
Unexpected value of __callee__ when including a module – is this a Ruby bug?
当通过 alias_method
创建的方法调用时,__callee__
忽略旧方法的名称(此处 xxx
),return 忽略新方法的名称方法,如下:
class Foo
def xxx() __callee__ end
alias_method :foo, :xxx
end
Foo.new.foo # => :foo
即使 xxx
是从超类继承的,这种行为仍然存在:
class Sup
def xxx() __callee__ end
end
class Bar < Sup
alias_method :bar, :xxx
end
Bar.new.bar # => :bar
鉴于以上两者,我希望当通过模块包含 xxx
时,同样的行为会发生。然而,事实并非如此:
module Mod
def xxx() __callee__ end
end
class Baz
include Mod
alias_method :baz, :xxx
end
Baz.new.baz # => :xxx
我希望 return 的值为 :baz
,而不是 :xxx
。
以上代码是使用Ruby 2.3.1p112 执行的。这是 __callee__
实现中的错误吗?或者 alias_method
?如果不是,谁能解释为什么模块包含的行为不同?
更新 1
我已经 posted this to the Ruby bug tracker 尝试提出一个答案。
更新 2
显然,我 not the only one to be surprised by this issue. I wonder whether Revision 50728 (which was meant to solve Bug 11046: __callee__
returns incorrect method name in orphan proc) 可能是相关的。
您可以在 Ruby 的内核模块中看到 __callee__
和 __method__
之间的区别。
不同之处在于分别调用了 prev_frame_callee()
和 prev_frame_func()
。我在 http://rxr.whitequark.org/mri/source/eval.c
找到了这些函数定义
简而言之,Foo 和 Bar 立即调用别名方法 foo 和 bar(它们是 xxx 的名称),而 Baz 必须找到 Mod 并从 Mod 调用 xxx。 __method__
查找原始被调用方法的 id,而 __callee__
查找最接近 __callee__
调用的被调用方法的 id。这在第 848 到 906 行的 eval.c
中更好地看到:在类似于 <something> -> called_id
与 <something> -> def->original_id
.[=21= 的 return 调用中寻找两种方法的区别]
另外,如果你看1.9.3版本的Kernel,你会发现这两种方法本来是一样的。因此,在某些时候,两者之间发生了有目的的变化。
这是一个错误,已于 3 天前关闭 with this note:
Seems fixed by r56592.
当通过 alias_method
创建的方法调用时,__callee__
忽略旧方法的名称(此处 xxx
),return 忽略新方法的名称方法,如下:
class Foo
def xxx() __callee__ end
alias_method :foo, :xxx
end
Foo.new.foo # => :foo
即使 xxx
是从超类继承的,这种行为仍然存在:
class Sup
def xxx() __callee__ end
end
class Bar < Sup
alias_method :bar, :xxx
end
Bar.new.bar # => :bar
鉴于以上两者,我希望当通过模块包含 xxx
时,同样的行为会发生。然而,事实并非如此:
module Mod
def xxx() __callee__ end
end
class Baz
include Mod
alias_method :baz, :xxx
end
Baz.new.baz # => :xxx
我希望 return 的值为 :baz
,而不是 :xxx
。
以上代码是使用Ruby 2.3.1p112 执行的。这是 __callee__
实现中的错误吗?或者 alias_method
?如果不是,谁能解释为什么模块包含的行为不同?
更新 1
我已经 posted this to the Ruby bug tracker 尝试提出一个答案。
更新 2
显然,我 not the only one to be surprised by this issue. I wonder whether Revision 50728 (which was meant to solve Bug 11046: __callee__
returns incorrect method name in orphan proc) 可能是相关的。
您可以在 Ruby 的内核模块中看到 __callee__
和 __method__
之间的区别。
不同之处在于分别调用了 prev_frame_callee()
和 prev_frame_func()
。我在 http://rxr.whitequark.org/mri/source/eval.c
简而言之,Foo 和 Bar 立即调用别名方法 foo 和 bar(它们是 xxx 的名称),而 Baz 必须找到 Mod 并从 Mod 调用 xxx。 __method__
查找原始被调用方法的 id,而 __callee__
查找最接近 __callee__
调用的被调用方法的 id。这在第 848 到 906 行的 eval.c
中更好地看到:在类似于 <something> -> called_id
与 <something> -> def->original_id
.[=21= 的 return 调用中寻找两种方法的区别]
另外,如果你看1.9.3版本的Kernel,你会发现这两种方法本来是一样的。因此,在某些时候,两者之间发生了有目的的变化。
这是一个错误,已于 3 天前关闭 with this note:
Seems fixed by r56592.