包含模块时__callee__的意外值 – 这是一个Ruby错误吗?
当通过alias_method
创建的方法调用时, __callee__
忽略旧方法的名称(此处为xxx
)并返回新方法的名称,如下所示:
class Foo def xxx() __callee__ end alias_method :foo, :xxx end Foo.new.foo # => :foo
即使从超类inheritancexxx
此行为也成立:
class Sup def xxx() __callee__ end end class Bar :bar
考虑到上述两种情况,我预计当通过模块包含xxx
时,相同的行为将成立。 但事实并非如此:
module Mod def xxx() __callee__ end end class Baz include Mod alias_method :baz, :xxx end Baz.new.baz # => :xxx
我希望返回值为:baz
,而不是:xxx
。
上面的代码是使用Ruby 2.3.1p112执行的。 这是__callee__
实现中的__callee__
吗? 或者也许是alias_method
? 如果没有,任何人都可以解释为什么模块包含行为不同?
更新1
我已将此发布到Ruby bug跟踪器 ,试图激起答案。
更新2
显然,我不是唯一一个对此问题感到惊讶的人。 我想知道修订版50728 (用于解决Bug __callee__
: __callee__
在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__
查找最接近被调用方法的id到__callee__
调用。 在eval.c
中第848到906行可以更好地看到这一点:在返回调用上查找两个方法的区别,类似于
vs
。
此外,如果从版本1.9.3查看内核,您将看到两个方法最初是相同的。 所以,在某些时候,两者之间有一个有目的的变化。
这是一个错误,它在3天前以此笔记关闭:
似乎由r56592修复 。