Procs

A proc is another encapsulation of code. Procs are assigned a variable name, and in this way are similar to methods. Blocks, on the other hand, are not assigned a variable name. You could define a Proc at the top of your file and call it later, but you could not do this with a Block.

In the example below, make_upper is a proc. Lambdas are a specific type of proc. Procs can be invoked using the call method.

make_upper = lambda { |n| n.upcase }

puts make_upper.call("test")

>> TEST

To pass a proc into a method, the proc needs to be converted into a block. Methods accept blocks as arguments, but not procs. In the example below, the ampersand prefix converts the make_upper proc into a block.

def say_hello
    yield("test")
end

make_upper = lambda { |n| n.upcase }

puts say_hello(&make_upper)

>> TEST

Notice in the example above that say_hello accepts a block, and the yield line passes the argument into the block, within the say_hello method. The block is evaluated within this method. The following code will not work, because the proc is being evaluated before it is passed into the method.

def say_hello
    yield
end

make_upper = lambda { |n| n.upcase }

puts say_hello(make_upper.call("test"))

The proc evaluates to a string, which is then passed into the say_hello method as an argument. However, when this method is executed, yield expects a block to be passed into the method. Since there is no block, the Ruby interpreter will throw an error.