Lambda vs Proc Vs Blocks

Blocks: They are called closures in other languages, it is a way of grouping code/statements. In ruby single line blocks are written in {} and multi-line blocks are represented using do..end An interesting fact about ruby is that all methods in ruby accept a block, even if you don’t declare a variable to accept it. So for example, take the method below

def my_method
  puts "Hello World"
end
It can accept a block as below
my_method { puts 'Hello Reader' }
The code is valid, but the output will have only puts “Hello World”. Why? because we passed in the block but it is not getting called. To run the block passed within your method you need to use the yield command.
def my_method
  puts 'Hello World'
  yield
end
Now it will print
Hello World.
Hello Reader.
But since we placed yield, it would now be expecting a block to be always passed in. So we need to write code to check if a block is given or not. The command to do that in ruby is block_given?.
def my_method
  puts 'Hello World'
  yield if block_given?
end
Proc Is a block itself, but it’s bound to a variable. So proc lets us save a code block to a variable, and pass it around in our application. A good example from the ruby docs is shown below
def gen_times(factor)
  return Proc.new {|n| n*factor }
end
times3 = gen_times(3)
times5 = gen_times(5)
times3.call(12)               #=> 36
times5.call(5)                #=> 25
times3.call(times5.call(4))   #=> 60
Lambda If you felt proc’s to be a refined version of block, then you can say lambda’s to be a refined version of proc. Lambda is essentially a proc itself but, the argument management is rigid. If it doesn’t get an argument or if the argument count is more or less it would raise an error. Example:
Proc.new {|a,b| [a,b] }.call(1,2,3)
=> [1,2]
lambda {|a,b| [a,b] }.call(1,2,3)
=>
ArgumentError: wrong number of arguments (3 for 2)
	from (irb):7:in `block in irb_binding'
	from (irb):7:in `call'
	from (irb):7
	from /home/dev1/.rvm/rubies/ruby-2.2.2/bin/irb:11:in `<main>'
2.2.2 :008 > Proc.new {|a,b| [a,b] }.call(1,2,3)
Since it’s now clearer to you on what block, proc and lambda is, let’s start with the difference between the three. Lambda shortcut notation.
code = -> (x) { x*x }
code.call 4
=> 16
  Lambda vs proc vs Blocks Proc and Blocks are the same, block is actually creating a single instance of proc which can’t be moved about in a variable. You can read about the similarity of Proc and Block here. If we do return within a lambda, it would just return from lambda and the method will continue.
def lambda_method
  lambda { return puts 'lambda' }.call
  return 'method'
end
lambda_method
=> method
If we do return with a proc, it would exit the method and return that value from proc.
def proc_method
  Proc.new { return puts 'proc' }.call
  puts 'method'
end
proc_method
=> proc
Arguments: The second difference between the three is the way they manage arguments. Block and Proc deal with them more or less the same, but lambda is totally different. Proc and Bloc, doesn’t mind about the number of arguments passed. But if we access a variable that is not present then it would raise an error.
def my_method
  yield 1, 2, 3
end
my_method { |x, y| puts "#{x} & #{y}" }
=> "1 & 2"
Proc.new { |x, y| puts "#{x} & #{y}" }.call(4, 5, 6)
=> "4 & 5"
lambda will raise an error
def my_method
  yield
end
my_method { |x, y| puts "#{x} & #{y}" }
Takeaways Block, Proc & Lambda are the three  different ways of grouping the code: Block:
  • Is in between the curly braces and in between do and end.
  • No issue with number of arguments.
  • Blocks are basically a proc without a name
Proc:
  • Similar behaviour as Block.
  • Can be stored in a variable and move around.
  • No issue with number of arguments.
  • Return within the proc would exit the method from where it is called.
Lambda
  • Same as Proc, but closer to a method.
  • Strict regarding the arguments it gets and it needs.
  • Return within a lambda would exit it from the lambda and the method would continue executing.
 ]]>