在Ruby中使用yield_method中的yield
是否可以在给定于define_method的块中生成yield关键字? 简单的例子:
class Test define_method :test do |&b| puts b # => # yield end end Test.new.test { puts "Hi!" }
此代码在Ruby 1.8.7和1.9.0中都会产生以下错误:
test.rb:4:在`test’中:没有来自test.rb的块(LocalJumpError):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!" }
我想这就是你要找的东西:
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/
您不能在define_method
块中使用yield
。 这是因为闭包捕获了块,观察:
def hello define_singleton_method(:bye) { yield } end hello { puts "hello!" } bye { puts "bye!" } #=> "hello!"
我不认为你的用户会因为你所陈述的方式而无法使用’yield’ – 语法与普通的Ruby方法定义语法完全不同,所以不太可能有任何混淆。
有关为什么不能将块隐式传递给此处的方法的更多信息: http : //banisterfiend.wordpress.com/2010/11/06/behavior-of-yield-in-define_method/