Ruby blocks, procs, lambdas and closures
Grappling with the differences between Ruby blocks, procs, lambdas, and closures is confusing at first. To fresh eyes they looks kinda weird and complicated compared to other parts of Ruby which are more familiar. But once you get them down you realize how cool and useful they really are. We are here to walk you through that learning curve. By the end of this you should have a solid idea of the basics of each and how they differ.
Lets start with a short example of each.
Block
Code blocks are commonly seen in Ruby enumerable methods. Some common Ruby methods which use blocks are: map, times and each. A block is simple a block of code that will be executed.
# Blocks are constructed by pairing either { } or do end.
[1, 2, 3, 4, 5].map { |num| num.odd? }
=> [true, false, true, false, true]
[1, 2, 3].each do |num|
puts num
end
1
2
3
=> [1, 2, 3]
Proc
A proc is very similar to a block. While the block is just a block of code a proc is an object which contains a block of code (a small but important difference). Procs are also created in a different manner; either using Proc.new or proc followed by a block of code. A proc can be declared using the { } or the do end syntax after the Proc.new or proc. After declaring a proc you invoke it with the .call method.
proc_object = Proc.new do
puts "Hello from the proc!"
end
$ proc_object.call
Hello from the proc!
=> nil
proc_object2 = proc { puts "In here." }
$ proc_object2.call
In here.
=> nil
Lambdas
A lambda is very similiar to a proc in that it is also an object that contains a code block for execution later. You create a lambda by writing either lambda or -> (which is funnily called the stabby lambda) then following it with a code block (either { } or do end). Lambdas are executed the same way as procs, by calling .call on the object.
little_lamb = lambda { "Mary had a little..." }
$ little_lamb.call
=> "Mary had a little..."
black_sheep = -> { "Baa baa black sheep..." }
$ black_sheep.call
"Baa baa black sheep..."
Closures
Finally closures. There is a reason that we saved them for last. A closure is a block of code that can be defined in one scope and then called later in another scope. So in Ruby Blocks, procs, and lambdas are all closures. It is a group that they all belong to rather than another defined thing in Ruby. Easiest definition so far right?
Wrap Up
So there is lots more to say about the differences between blocks, procs, and closures in Ruby. For instance did you try out defining a lambda in irb? You would see that the object returned says it is a Proc with a (lambda) on the end of it:
$ proc_object2 = proc { puts "In here." }
=> #<Proc:0x000001afb306a450 (irb):8>
$ little_lamb = lambda { "Mary had a little..." }
=> #<Proc:0x000001afb2f6b900 (irb):10 (lambda)>
All that will have to wait for another blog post though. Hopefully this post cleared up the basic differences between them.
If you have questions about this post or anything wasn’t clear enough then drop me an email (john@dragonastronauts.com) or a comment and I will get back to you.