我正在尝试将Ruby 1.8应用程序升级到1.9并在此处遇到一些障碍。在Ruby 1.8.7中,我可以将一个块传递给Builder 3.0.0,并按预期调用它:
1.8.7 :003 > @builder = Builder::XmlMarkup.new
1.8.7 :004 > block = lambda { puts "foo" }
1.8.7 :005 > @builder.tag(&block)
foo
但是在1.9中,我收到了这个错误:
1.9.3p0 :002 > @builder = Builder::XmlMarkup.new
1.9.3p0 :003 > block = lambda { puts "foo" }
1.9.3p0 :004 > @builder.content(&block)
ArgumentError: wrong number of arguments (1 for 0)
from (irb):3:in `block in irb_binding'
from /Users/dev/.bundle/ruby/1.9.1/gems/builder-3.0.0/lib/builder/xmlbase.rb:155:in `call'
...
并重写为一个stabby lambda(这只是语法糖,对吗?)没有帮助:
1.9.3p0 :006 > block = -> { puts "foo" }
1.9.3p0 :007 > @builder.content(&block)
ArgumentError: wrong number of arguments (1 for 0)
传递一个实际的块而不是一个引用可以工作:
1.9.3p0 :008 > @builder.content { puts "foo" }
foo
帮助?
答案 0 :(得分:6)
这实际上是因为在ruby 1.9中,lambda和proc的行为略有不同。想想lambda,在数学上是精确的,需要指定参数的确切数量,而proc表现出ruby 1.8更宽松的行为。例如,
a = lambda {|v| p v }
a.call() # ArgumentError: wrong number of arguments (0 for 1)
a.call(1) # prints "1"
a.call(1, 2) # ArgumentError: wrong number of arguments (2 for 1)
b = proc {|v| p v }
b.call() # prints "nil"
b.call(1) # prints "1"
b.call(1, 2) # prints "1"
请注意,这两个对象都是Proc类型,但可以通过.lambda进行区分?方法
a.class # => Proc
a.lambda? # => true
a.arity # => 1 (number of parameters)
b.class # => Proc
b.lambda? # => false
b.arity # => 1 (number of parameters)
答案 1 :(得分:0)
block.call(self)
换句话说,它将自身作为参数传递给块。在Ruby 1.8中,块可以自由地忽略它,但在1.9中,它必须声明所有参数。因此:
1.9.3p0 :023 > block = lambda { |dummy| puts "foo" }
1.9.3p0 :024 > @builder.content(&block)
foo
耶!