Arup Rakshit
Arup Rakshit

Reputation: 118261

Confusion with `Call` to `block` created as `Proc` object

I have created an object calling Proc.new and passing to it a block as an argument:

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

I didn't use any splat operator(*) also. But how does then block parameter x being able to ignore the extra arguments?

When we do the same we get a definite error, but why that's not the case with block parameter?

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>'

Upvotes: 1

Views: 70

Answers (2)

Leo Correa
Leo Correa

Reputation: 19789

Procs convert missing arguments to nil whereas lambda does not.

If you want to be tolerant about errors then use Procs. Otherwise you'll want to go with 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>'

Upvotes: 2

Intrepidd
Intrepidd

Reputation: 20868

That's how Procs work, internally, they don't care if too much arguments are passed.

Proc#call will take an array of arguments and bind them to the arguments of the block, and won't complain if the count does not match.

Proc Lambdas, however, will complain about it, that's one of the differences between them and regular Procs :

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>'

Upvotes: 1

Related Questions