包含模块时__callee__的意外值 – 这是Ruby的错误?

当通过alias_method创建的方法调用时,__callee__将忽略旧方法名称(这里为xxx),并返回新方法名称,如下所示:
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

我希望返回值为:baz,而不是:xxx.

上面的代码是使用Ruby 2.3.1p112执行的.这是执行__callee__的错误吗?或者可能是alias_method?如果没有,任何人都可以解释为什么模块包含行为不同?

更新1

我有posted this to the Ruby bug tracker尝试挑起一个答案.

更新2

显然,我是not the only one对这个问题感到惊讶.我想知道Revision 50728(这是为了解决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.

另外,如果从1.9.3版本看内核,你会发现这两个方法最初是一样的.所以,在某些时候,两者之间有一个有意义的变化.

相关文章

validates:conclusion,:presence=>true,:inclusion=>{...
一、redis集群搭建redis3.0以前,提供了Sentinel工具来监控各...
分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣...
上一篇博文 ruby传参之引用类型 里边定义了一个方法名 mo...
一编程与编程语言 什么是编程语言? 能够被计算机所识别的表...
Ruby类和对象Ruby是一种完美的面向对象编程语言。面向对象编...