Ruby has two kinds of anonymous function: blocks, and procs.

Block

A block is a syntactic element. The only things you can do with these are:

  • pass them to methods as the “default block” argument
  • in a method that’s been called with a default block, yield zero or more arguments to it, getting a result
  • in a method that’s been called with a default block, capture it into a Proc with an ampersand in the arguments list
Proc

A Proc is an object. You can do just about anything with it, including turn it back and forth from a block.</dd> </dl><h1>Developing with Blocks</h1>

Using blocks with somebody else’s API is intuitive:

(1..5).map{|n| n * 3} #=> [3, 6, 9, 12, 15]

Making an API that uses blocks can be easy too:

module Object
  def with
    yield self
  end
end

# calling
"hello".with{|h| puts h}
# prints "hello"

If you yield more than once, you run the block multiple times.

Developing with Procs

How do you even make a Proc?

doubler = proc{|n| n * 2}
#=> #<Proc:0x007f8e938d8618@(irb):1>

There’s a few methods, like proc, that turn a block into a Proc. lambda is very similar. They’re easy to write:

def my_proc(&block)
  block
end

tripler = my_proc{|n| n * 3}
#=> #<Proc:0x007f8e9506d170@(irb):5>

The ampersand in the argument list to my_proc is what transforms the block into a Proc, and then we simply return it.

You can use the ampersand to turn a Proc into a block too:

(1..5).map doubler
# ArgumentError: wrong number of arguments(1 for 0)

(1..5).map &doubler
#=> [2, 4, 6, 8, 10]

And you can call a Proc directly without having to turn it into a block too:

doubler.call 4
#=> 8

doubler[5]
#=> 10

doubler.(6) # the dot before the parentheses is significant
#=> 12

Blocks and Procs can be confusing. I hope this helps!