是否可以在给定于define_method的块中生成 yield 关键字?简单的例子:
class Test
define_method :test do |&b|
puts b # => #<Proc:...>
yield
end
end
Test.new.test {
puts "Hi!"
}
此代码在Ruby 1.8.7和1.9.0中都会产生以下错误:
test.rb:4:在`test'中:没有给出块(LocalJumpError) 来自test.rb:8
奇怪的是 b 块变量!= nil
,但block_given?
返回false。有意的Ruby行为是不是通过 Proc 对象识别块?
修改:关于 Beerlington 的回答:b.call()
不是我想要的。块变量仅用于指示实际给出块,并且在define_method中未检测到。
yield
代替block.call
我愿意为Ruby中定义新类的方式编写一些扩展,因此任何代码当我使用扩展时,你可以接受纯Ruby编写。
因此不能考虑类似的语义,因为这会强制我的库的用户只使用一种正确的方法来传递一个块。这会破坏TIMTOWTDI规则,并且不会使我的库透明。
以下代码可以简化为上面的代码,因为my_def
使用define_method
:
require 'my_library'
class Test
# client can write 'my_def' instead of 'def' since
# my_library extends Class class
my_def :test, "some parameter" do
yield # oh no, error :(
end
end
Test.new.test {
puts "Hi!"
}
答案 0 :(得分:21)
我认为这就是你要找的东西:
class Test
define_method :test do |&b|
b.call
end
end
Test.new.test {
puts "Hi!"
}
更多http://coderrr.wordpress.com/2008/10/29/using-define_method-with-blocks-in-ruby-18/
答案 1 :(得分:18)
您无法在yield
块中使用define_method
。这是因为闭包捕获了块,观察:
def hello
define_singleton_method(:bye) { yield }
end
hello { puts "hello!" }
bye { puts "bye!" } #=> "hello!"
我认为您的用户不会介意无法以您所声明的方式使用'yield'----语法 nothing 就像普通的Ruby方法定义语法一样,所以不太可能任何困惑。
有关无法将块隐式传递给此处的方法的更多信息:http://banisterfiend.wordpress.com/2010/11/06/behavior-of-yield-in-define_method/