当我编写采用可选块的方法时,我通常使用类似
的方法block.call if block_given?
但是,在如下动态定义的方法中,block_given?
似乎不起作用。
class Foo
%w[bar baz].each do |method_name|
define_singleton_method(method_name) do |&block|
puts "Was #{method_name} given a block? #{block_given?}"
puts block.call
end
end
end
Foo.bar { puts 'I am a block' }
按预期调用块,但block_given?
返回false。
为什么会这样?
答案 0 :(得分:9)
块是闭包,因此它们记住局部变量(例如method_name
)。他们还会记住阻止:yield
和block_given?
正在寻找在调用define_method
时处于活动状态的阻止,而不是传递给bar
的阻止。没有一个,所以给出的块返回false。
更好的说明是
def create_method
define_singleton_method('foo') do |&block|
puts "Was given a block? #{block_given?}"
puts yield
puts block.call
end
end
create_method {'block passed to create_method'}
foo {'block passed to the created method'}
输出
Was given a block? true
block passed to create_method
block passed to the created method