混淆与`call`到`block`创建为`Proc`对象

时间:2013-03-11 14:32:13

标签: ruby

我创建了一个调用Proc.new的对象,并将一个块作为参数传递给它:

a = Proc.new{|x| x = x*10; puts(x)}
#=> #<Proc:0xd26fd8@(irb):3>
a.call(10)
#100
#=> nil
a.call(10,20)
#100
#=> nil
a.call(10,20,40)
#100
#=> nil

我也没有使用任何splat operator(*)。但是,如何阻止参数x能够忽略额外的参数?

当我们这样做时,我们得到一个明确的错误,但为什么不是块参数的情况呢?

def show(x)
print "X::#{x}"
end
#=> nil
show(10)
#X::10#=> nil
show(10,20)
#ArgumentError: wrong number of arguments (2 for 1)
#        from (irb):6:in `show'
#        from (irb):10
#        from C:/Ruby193/bin/irb:12:in `<main>'

2 个答案:

答案 0 :(得分:2)

Procs将缺少的参数转换为nil,而lambda则不会。

如果您想容忍错误,请使用Procs。否则你会想要lambda

l = ->(x) { x = x * 10; puts x }
=> #<Proc:0x007fada3be9468@(pry):12 (lambda)>
l.call(10, 20)
ArgumentError: wrong number of arguments (2 for 1)
from (pry):12:in `block in <main>'

答案 1 :(得分:1)

这就是Procs在内部工作的方式,他们并不关心是否传递了太多的论据。

Proc#call将获取一个参数数组并将它们绑定到块的参数,如果计数不匹配则不会抱怨。

然而,Proc Lambdas会抱怨它,这是他们和常规程序之间的差异之一:

2.0.0p0 :006 > r = lambda { |x| puts x }
 => #<Proc:0x007fac6913b600@(irb):6 (lambda)>
2.0.0p0 :007 > r.call(1,2)
ArgumentError: wrong number of arguments (2 for 1)
from (irb):6:in `block in irb_binding'
from (irb):7:in `call'
from (irb):7
from /Users/Intrepidd/.rvm/rubies/ruby-2.0.0-p0/bin/irb:16:in `<main>'