# If the last parameter in a method definition is prefixed with an ampersand, any associated block # is converted to a Proc object and that object is assigned to the parameter. # It must be the last argument in the parameter list def do_math_operation(amount, &block) block.call(amount) # OR yield(amount) end result = do_math_operation(5) {|amount| amount * 2} => 10 # A proc is a reusable object oriented block , a block is actually a proc that can't be saved block.class => Proc # The same above can be done using proc def do_math_operation(amount, proc) proc.call(amount) # yield won't work! end multiply_by_2 = Proc.new do |n| n * 2 end result = do_math_operation(5, multiply_by_2) => 10 # The same above can be done using lambda def do_math_operation(amount, lambda) lambda.call(amount) # yield won't work! end multiply_by_2 = lambda{ |n| n * 2 } result = do_math_operation(5, multiply_by_2) => 10 # Differences between Lambda and Procs # 1- Lambda checks for number of parameters , throw an exception if less or more parameters were passed # ex: lambda = lambda{ |str1, str2| "#{str1}, #{str2}"} lambda.call('str1', 'str2') => str1, str2 lambda.call('str2','str2','str3') ArgumentError: wrong number of arguments (3 for 2) proc = Proc.new{ |str1, str2| "#{str1}, #{str2}" } proc.call("str1") => str1, # 2- Lambda in a method will return the value to the method and the method continues normally, while Proc stops method execution def proc_return Proc.new{ |n| puts n } puts 'see me if you can' end def lambda_return lambda{ |n| puts n } puts 'hi, i am here' end proc_return => Proc lambda_return => hi, i am here # Note proc can't have a return in it , while lambda can # The same can be done using method objects def do_math_operation(amount, method) block.call(amount) # yield won't work! end def multiply_by_2(n) n * 2 end result = do_math_operation(5, method(:multiply_by_2)) => 10 # Method objects will act like lambda , only lambda is anonymous