Blocks, Procs & Lambdas revisited

Blocks, Procs & Lambdas are one of the most fun things in ruby but also very difficult to understand. This is my attempt to make these things a little simple for you.

What are blocks?

A piece of ruby code within a do..end or within curly braces {} is a block. For ex:

[1,2,3,'a'].select do |d|
  d.is_a?Integer
end

or

[1,2,3,'a'].select {|d| d.is_a?Integer}

We should also notice here that blocks breaks one of the most basic and yet powerful fundamentals of ruby that everything in ruby is an object. Well blocks are not objects. They are just piece of ruby code.

Now imagine when we have more than 1 array to select only the integer values. Ex:

[1, 2, 3, 'a'].select {|d| d.is_a?Integer}
['b', 'c', 5].select {|d| d.is_a?Integer}
['a', nil, 4 ].select {|d| d.is_a?Integer}

This is not very ruby like. We clearly breaks the DRY(Do not repeat yourself) rule. We are repeatedly writing the same block of code again and again. Now only if we could somehow save the block of code in a variable. Enter Proc.

What is a Proc?
In most simple way, Procs are named blocks. For ex:

p = Proc.new {|d| d.is_a?Integer}
puts p.class => Proc

So p is an object of class Proc unlike blocks.
Now we know how to save a block of code in a variable, lets use that knowledge to make our code dry.

[1, 2, 3, 'a'].select(&p)
['b', 'c', 5].select(&p)
['a', nil, 4 ].select(&p)

Then, what about lambda.

What is a lambda?
Lambda is just like a proc with very subtle differences between them. But before we get there, lets see how do we declare a lambda and how to use it. Ex:

p = lambda {|d| d.is_a?Integer}
puts p.class => Proc
[1, 2, 3, 'a'].select(&p)
['b', 'c', 5].select(&p)
['a', nil, 4 ].select(&p)

Yes, lambda and proc both belong to class Proc.

Then, is there any difference between them?

Difference between proc and lambda:

1. Proc do not care about the number of arguments passed. It assigns nil to any missing argument.
Ex:

p = Proc.new {|d| p d.class}
p.call => NilClass
p.call(3) => Fixnum

But had it been a lambda,

p = lambda {|d| p d.class}
p.call would raise
ArgumentError: wrong number of arguments (0 for 1)

, as it cares about its arguments unlike Procs.

2. when lambda is called, it returns control back to the calling method. Whereas Proc does not go back to the calling method. Ex:

def test_proc
  p = Proc.new {return 'In proc'}
  p.call
  'In test_proc method'
end
test_proc=> 'In proc'
def test_lambda
  p = lambda {return 'In lambda'}
  p.call
  'In test_lambda method'
end
test_lambda=> 'In test_lambda method'

I hope this would make understanding these concepts a little bit easier.

Advertisements

One thought on “Blocks, Procs & Lambdas revisited

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s