Advertisement
Ruby

Ruby on Rails Study Guide: Blocks, Procs, and Lambdas

by

Ruby is a language with a set of powerful features - the most powerful arguably being Blocks, Procs, and Lambdas. In short, these features allow you to pass code to a method and execute that code at a later time. Despite regularly using these features, many developers don't fully understand the subtle differences between them.

Study Guides: When applying for a programming job, you’ll often be presented with a quiz that intends to determine your level of knowledge and experience in a given subject. The various articles in this series provide condensed solutions to the questions that you might expect to see on such tests.

Blocks

A block is code that is implicitly passed to a method through the use of either curly braces, {...}, or do...end syntax. It's common convention to use {...} for single line blocks, and do...end for multi-line blocks. For example, the following blocks are functionally the same:

array = [1,2,3,4]
array.map! do |n|
  n * n
end
=> [1, 4, 9, 16]

array = [1,2,3,4]  
array.map! { |n| n * n }  
=> [1, 4, 9, 16]

The magic behind a block is the yield keyword; it defers the execution of the calling method in order to evaluate the block. The result of the block, if any, is then evaluated by any remaining code in the method. The yield statement can also accept parameters, which are then passed into and evaluated within the block. Tying this together, a simple example of the map! above method would be the following:

class Array
  def map!
    self.each_with_index do |value, index|
      self[index] = yield(value)
    end
  end
end

This simple representation of map! calls the each_with_index method and replaces the item at the given index with the result of the block. While this is a trivial example of block usage, it helps to show yield's power. The uses of blocks in Ruby are endless, and we frequently use them in our code.


Procs

The above example demonstrates a minor limitation of blocks: they are syntax and disposable. We have to retype blocks every time we reuse them on different arrays, but we can store a block for later use by using the Ruby Proc Object. We can store a Proc in a variable, and then explicitly pass it to any method that accepts a callable object. Rewriting the above example as a Proc would look like the following:

number_squared = Proc.new { |n| n * n }

Let's modify our map! method to accept and call the Proc object:

class Array
  def map!(proc_object)
    self.each_with_index do |value, index|
      self[index] = proc_object.call(value)
    end
  end
end

array = [1,2,3,4]

array.map!(number_squared)

=> [1, 4, 9, 16]

Take note that we no longer use the yield keyword; instead, we directly use the call method on the Proc object, passing it the value from the array. We receive the same result as before, but we store our block in a variable to reuse a later time.


Lambdas

Lambda function are almost identical to Procs but with two key differences. First, a lambda checks the the number of arguments it receives and returns an ArgumentError if they do not match. For example:

l = lambda { "I'm a lambda" }
l.call
=> "I'm a lambda"
l.call('arg')
ArgumentError: wrong number of arguments (1 for 0)

Second, lambdas provide diminutive returns - meaning that when a Proc encounters a return statement in it's execution, it halts the method and returns the provided value. Lambdas on the other hand, return their value to the method, allowing it to continue:

def proc_math
  Proc.new { return 1 + 1 }.call
  return 2 + 2
end

def lambda_math
  lambda { return 1 + 1 }.call
  return 2 + 2
end

proc_math # => 2  
lambda_math # => 4

As you can see proc_math hits the return statement inside the Proc and returns the value of 2. In contrast, lambda_math skips the return statement and evaluates 2 + 2 instead.

One final note: Ruby 1.9 introduces the new "stabby" lambda syntax (represented with ->), which is functionally identical to the traditional lambda syntax, but the "stabby" syntax is much cleaner.


Conclusion

In this study guide, we've covered the key differences between Blocks, Procs, and Lambdas:

  • Blocks are single use.
  • Procs exist as objects.
  • Lambdas have strict argument checking.

For a more in-depth review, I recommend the following resources:

Related Posts
  • Code
    Web Development
    Testing Your Ruby Code With Guard, RSpec & Pry: Part 2Ruby wideretina preview
    Continue learning test-driven development in Ruby with Guard, RSpec and Pry.Read More…
  • Code
    Web Development
    Testing Your Ruby Code With Guard, RSpec & PryRuby wideretina preview
    Learn the basics of test-driven development in Ruby along with many common web development tools such as Guard, RSpec, and Pry, among others. Read More…
  • Computer Skills
    App Training
    Writing Destinations for DropzoneDropzone400
    Dropzone is not just another FTP upload client, but a great utilities platform for processing files and text. Dropzone is a collection of destinations that can have two types of actions: drag and drop action and/or a click action. There are a lot of pre-programmed destinations to use, but you can also write your own destinations in Ruby!Read More…
  • Code
    WordPress
    Mastering WordPress Meta Data: Understanding and Using ArraysMetadata
    In the first part of this series, we covered what WordPress meta data is, how it can be retrieved, and the various data types (such as objects or arrays) in which it can be returned. Now it's time to learn about the different types of arrays. When you write an array manually you know what its structure is an what the name of each index is. But when you are building arrays by querying a database, you are going to need to do some detective work to determine the structure of the data returned and the names of the indexes.Read More…
  • Code
    iOS SDK
    Objective-C Succinctly: Blocks0e5ds8 preview image@2x
    Blocks are actually an extension to the C programming language, but they are heavily utilized by Apple's Objective-C frameworks. They are similar to C#'s lambdas in that they let you define a block of statements inline and pass it around to other functions as if it were an object.Read More…
  • Code
    Scala
    Building Ribbit in ScalaRibbit scala retina preview
    In this tutorial we will implement the Ribbit application in Scala. We'll be covering how to install the Play web framework, a NetBeans plugin for it, and finally the code in Scala. If you are new to Scala, check out this previous tutorial which will help you set up your environment and provides you with a general platform that you can build upon. Even though the essence of Ribbit is to create/send/read Ribbits (our version of tweets), we will spend a large part of this tutorial explaining how Play works, authentication, and persistence. After these are in place, the rest becomes much easier. We will also implement ribbit creation, submission and listing out all ribbits. Following someone, advanced user settings, and direct messages will be an extra assignment for you to complete on your own. I am sure if you manage to follow along with this tutorial and create Ribbit as explained below, these three functionalities will be easily accomplished as homework.Read More…