Thursday, 23 October 2014

What is the difference between Proc and Lambda?

What is the difference between Proc and Lambda?

      Blocks are syntactic structures in Ruby; they are not objects, and cannot be manipulated
as objects. It is possible, however, to create an object that represents a block. Depending
on how the object is created, it is called a proc  or a lambda .

       Procs have block-like behavior and lambdas have method-like behavior. Both, however, are instances of class Proc .

       Creating & invoking procs:
             p = Proc.new {|x,y| x+y }
             p.call(1,2)
       
       Creating & invoking Lamdas:
            succ = lambda {|x| x+1}  =>Ruby1.8
               succ = ->(x){x>0} =>Ruby1.9
                succ.call(1)

        In a lambda-created proc, the return statement returns only from the proc itself
        In a Proc.new-created proc, the return statement is a little more surprising: it returns control not just from the proc, but also from the method enclosing the proc!


      Differences:
        
Procs
Lambda
 A proc is the object form of a block, and it behaves like a block.

 Calling a proc is like yielding to a block.

 A proc is like a block, so if you call a proc that executes a return  statement, it attempts
to return from the method that encloses the block that was converted to the proc.
For Example:

def test
puts "entering method"
p = Proc.new { puts "entering proc"; return }
p.call  # Invoking the proc makes method return
puts "exiting method"  # This line is never executed
end
test

 break to do the same thing like return in a proc.


  proc handles the arguments it receives  flexibly:discarding extras, silently adding nil  for omitted arguments.

   p = Proc.new {|x,y| print x,y }
   p.call(1,2)  # prints 1,2
   p.call(1)  # prints 1, nil
 A lambda has slightly
modified behavior and behaves more like a method than a block.
 whereas calling a lambda is like invoking a method.

 A return  statement in a lambda returns from the lambda itself, not from the method that surrounds the creation site of the lambda:
For Example:
def test
puts "entering method"
p = lambda { puts "entering lambda"; return }
p.call
 # Invoking lambda does not make the method #return
puts "exiting method" 
# This line *is* executed now
end
test

break to do the same thing like return in a lambda.

 Lambdas are not flexible in this way; like methods, they must be invoked with precisely
the number of arguments they are declared with:

         l = lambda {|x,y| print x,y }
         l.call(1,2) # This works
         l.call(1) # Wrong number of arguments

   next statement works the same in a block, proc, or lambda.
   redo also works the same in procs and lambdas.
   retry is never allowed in procs or lambdas: using it always results in a LocalJumpError.
   raise behaves the same in blocks, procs, and lambdas. Exceptions always propagate up the call stack

No comments:

Post a Comment