请考虑以下不同方法来定义方法m
:
方法1:
class C
def m; yield; end
end
方法2:
class C
def initialize
(class << self; self; end).class_eval do
define_method(:m){|&b| b.call }
end
end
end
方法3:
class C
def initialize
(class << self; self; end).class_eval do
define_method(:m){puts block_given?; yield}
end
end
end
然后我可以使用m
调用Object#send
。
o = C.new
o.send(:m) {puts 'test'}
使用方法1或方法2调用m
时工作正常,方法3会出现此错误:
no block given (yield) (LocalJumpError)
我理解一个块不是一个对象,而只是方法调用语法的一部分,你不能将一个隐式块从一个函数传递给另一个函数而不用像这样模糊的东西:
def printer
yield
end
def proxy
printer &Proc.new
end
proxy { puts "&Proc.new probably creates Proc object from block"}
但在那种情况下,为什么方法1有效?获得一个可以解释幕后发生的事情的答案真是太棒了。
答案 0 :(得分:3)
方法3的问题在于范围。 yield
是指传递给initialize
的块,如果有的话。它没有引用传递给m
的块。由于您在o
之前创建了C.new
而没有阻止,因此缺少预期的yield
,这会导致错误。
在方法1中,yield
指的是传递给m
的块。在方法2中,b
指的是从传递给m
的块转换的proc。