Programming ≈ Fun

Written by Krešimir Bojčić

Grokking the Ruby Blocks in 10 Minutes

I am assuming you are intrigued about Ruby blocks. My assumption is that you are aware that they exist but unsure of what they are or how to use them. From my experience main obstacle in understanding them is introduction of multiple concepts all at once. You need to understand closures and procs to understand blocks. Also Ruby mix-up with lambda vs. proc debate is not helpful either. There are some great posts about the subject. For example Understanding Ruby Blocks Procs and Lambdas.

Nightmare at 20,000 Feet
Nightmare at 20,000 Feet via Wikipedia

I am going to bluntly ignore the details and just give the 20,000 feet look at it.

Block in Ruby is just another type of variable.

We all understand this:

def hello(name)
  puts "Hello #{name}."
end

hello "unfortunate reader" #=> Hello unfortunate reader.

We also understand that the functions in Ruby are a first class citizens; you can declare a function and save it for later usage like this:

function = ->(name){ puts "Hello #{name}." }  #defining for later execution

def hello(function, name)
  function.call(name)
end

hello function, "unfortunate reader" #=> Hello unfortunate reader.

It turns out block is just syntax sugar for that kind of variable.

Here is the deal: You don’t give a name to a function and it has to be the last argument. Let’s call it a block.
This so called block is (before being used) transformed to a function with that silly ampersand.

def hello(name, &block)
  block.call(name)
end

hello("unfortunate reader") {|name| puts "Hello #{name}." }  #=> Hello unfortunate reader.

This fact is somewhat shadowed with the use of implicit blocks and a special keyword yield. But don’t let that fool you. It is still just a (hidden) variable and being treated exactly the same as the above block.

def hello(name)
  yield(name)
end

hello("unfortunate reader") { |name| puts "Goodby #{name}." } #=> Goodby unfortunate reader.