When invoked via a method created by alias_method
, __callee__
ignores the name of the old method (here xxx
) and returns the name of the new method, as below:
当通过alias_method创建的方法调用时,__callee__忽略旧方法的名称(这里是xxx)并返回新方法的名称,如下所示:
class Foo
def xxx() __callee__ end
alias_method :foo, :xxx
end
Foo.new.foo # => :foo
This behavior holds even when xxx
is inherited from a superclass:
即使xxx继承自超类:
class Sup
def xxx() __callee__ end
end
class Bar < Sup
alias_method :bar, :xxx
end
Bar.new.bar # => :bar
Given both of the above, I would expect that the same behavior would hold when xxx
is included via a module. However, that is not the case:
考虑到上述两种情况,我希望通过模块包含xxx时,也能保持相同的行为。然而,情况并非如此:
module Mod
def xxx() __callee__ end
end
class Baz
include Mod
alias_method :baz, :xxx
end
Baz.new.baz # => :xxx
I expect the return value to be :baz
, not :xxx
.
我希望返回值是:baz,而不是:xxx。
The above code was executed using Ruby 2.3.1p112. Is this a bug in the implementation of __callee__
? Or maybe of alias_method
? And if not, can anyone explain why module inclusion behaves differently?
上面的代码是使用Ruby 2.3.1p112执行的。这是执行__callee__的一个bug吗?或者alias_method吗?如果没有,谁能解释为什么模块包含行为不同?
UPDATE 1
更新1
I've posted this to the Ruby bug tracker to try to stir up an answer.
我已经把这贴在Ruby bug跟踪器上,试图找出答案。
UPDATE 2
更新2
Apparently, I'm 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) might be related.
显然,我不是唯一对这个问题感到惊讶的人。我想知道修订50728(这是为了解决Bug 11046: __callee__在孤立程序中返回不正确的方法名)是否相关。
2 个解决方案
#1
1
You can see the difference between __callee__
and __method__
in Ruby's Kernel module.
您可以在Ruby的内核模块中看到__callee__和__method__之间的区别。
The difference is the calls prev_frame_callee()
and prev_frame_func()
, respectively. I found these function definitions at http://rxr.whitequark.org/mri/source/eval.c
区别在于分别调用prev_frame_callee()和prev_frame_func()。我在http://rxr.whitequark.org/mri/source/eval.c找到了这些函数定义
In short, Foo and Bar are immediately calling the aliased methods foo and bar (which are names for xxx), while Baz has to find Mod and call xxx from Mod. __method__
looks for the original called method's id, while __callee__
looks for the closest called method's id to the __callee__
call. This is better seen in eval.c
at lines 848 to 906: look for the difference in the two methods on the return calls similar to <something> -> called_id
vs <something> -> def->original_id
.
简而言之,Foo和Bar立即调用别名方法Foo和Bar xxx(名字),而记者从国防部找到Mod,叫xxx。__method__查找原始称为方法的id,而__callee__寻找最接近的方法__callee__调用的id。在eval可以更好地看到这一点。c在第848到906行:在返回调用中查找类似于
Also, if you look at the Kernel from version 1.9.3, you will see that the two methods originally were the same. So, at some point, there was a purposeful change between the two.
同样,如果您查看1.9.3版本中的内核,您将看到这两个方法最初是相同的。因此,在某种程度上,两者之间有一个有目的的改变。
#2
1
This was a bug, and it was closed 3 days ago with this note:
这是一个bug,它在3天前关闭了,上面有这样的注释:
Seems fixed by r56592.
似乎由r56592固定。
#1
1
You can see the difference between __callee__
and __method__
in Ruby's Kernel module.
您可以在Ruby的内核模块中看到__callee__和__method__之间的区别。
The difference is the calls prev_frame_callee()
and prev_frame_func()
, respectively. I found these function definitions at http://rxr.whitequark.org/mri/source/eval.c
区别在于分别调用prev_frame_callee()和prev_frame_func()。我在http://rxr.whitequark.org/mri/source/eval.c找到了这些函数定义
In short, Foo and Bar are immediately calling the aliased methods foo and bar (which are names for xxx), while Baz has to find Mod and call xxx from Mod. __method__
looks for the original called method's id, while __callee__
looks for the closest called method's id to the __callee__
call. This is better seen in eval.c
at lines 848 to 906: look for the difference in the two methods on the return calls similar to <something> -> called_id
vs <something> -> def->original_id
.
简而言之,Foo和Bar立即调用别名方法Foo和Bar xxx(名字),而记者从国防部找到Mod,叫xxx。__method__查找原始称为方法的id,而__callee__寻找最接近的方法__callee__调用的id。在eval可以更好地看到这一点。c在第848到906行:在返回调用中查找类似于
Also, if you look at the Kernel from version 1.9.3, you will see that the two methods originally were the same. So, at some point, there was a purposeful change between the two.
同样,如果您查看1.9.3版本中的内核,您将看到这两个方法最初是相同的。因此,在某种程度上,两者之间有一个有目的的改变。
#2
1
This was a bug, and it was closed 3 days ago with this note:
这是一个bug,它在3天前关闭了,上面有这样的注释:
Seems fixed by r56592.
似乎由r56592固定。