Ruby Blocks, Procs, Lambdas

Blocks

A ruby block is the piece of code that is executed. This code can be executed using curly brackets {} or a pair of "do" and "end". Blocks can be used in conjunction with #each, #times, #collect, and other built-in methods. For example, in figure below are two ways in which we can print out the strings in the array.

The yield statement invokes a block. A yield statement can also be used with parameters for invoking a block. Let's take a look at this next example.

When yield is executed it runs the test statement "now in the block". Basically when yield is in the block it will run the test method with the block "{puts 'now in the block'}".

This is how a yield statement would look like with parameters.

By interpolating the names (inserting the argument "name") into the string we can call yield with an argument which will be used in the show_name method and the corresponding block.

Procs

In Ruby blocks cannot be saved to variables to write D.R.Y. code because blocks aren't objects. Procs come to the rescue here because they are objects themselves. Procs are "saved" blocks. They are simple to define. In the example below we create a new Proc for "multiply" and use multiply for both an_array and another_array without having to rewrite the math block. We just call "&"multiply". Collect! and Map! do the same thing; they both take each element from the array and replace the original element with the new element. Also procs can be called on via the ".call" method. If we had a new proc with the code block of "puts "hello!", we could use the name of that proc and add ".call" and the proc would run. We can also use the "&" to convert symbols as procs. In the example below, we turn the elements in string_array into integers by using the ":to_i" symbol.

Lambdas

Lambdas are very similar to procs. Lambda syntax is different from procs though. Previously we saw that a new proc would need "variable_name = Proc.new {code block}". Lambdas replace "Proc.new" with "lambda". Lambdas also use the ampersand to call the "stored" block. The below is an example of lambda syntax.

There are two main differences between procs and lambdas. The first differences is that lambda checks the number of arguments passed to it, whereas procs took whatever was passed to it. However procs would output "nil" for the extra arguments. Lambdas will throw errors if unexpected arguments were passed to it. Second, when a lambda returns it passes control back to the calling method but a proc immediately returns WITHOUT going back to the calling method. Need a visual explanation? Check out the example below.

The proc example immediately returns "Celica will win!" without going back to celica_gtr_proc method. On the other hand, the lambda example goes back to the celica_gtr_lambda method and outputs "GTR will win!".