A Quick Look at Ruby blocks, procs, and lambdas

Colter Ulrich
3 min readJan 31, 2021

Blocks, Procs, Lambdas

Blocks

If you’ve written any Ruby, chances are you are familiar with blocks. A block is a chunk of code enclosed between curly brackets, or between the do and end keywords. Just like a method, it can take parameters (at the very beginning of the block, between pipes). This means that we can pass values to blocks, and also receive values from blocks.

We can call a block using the yield keyword, like so:

def print_once
yield
end
print_once { puts “I ran.” }# => “I ran.”def print_twice
yield
yield
end
print_twice { puts “I ran.” }# => “I ran.”# => “I ran.”

Lastly, blocks can be given a name to explicitly pass it to another method, or to save as a variable for later use.

def explicit_block(&block)
block.call #same as yield
end
explicit_block { puts “I’m an explicit block!” }# => “I’m an explicit block!”

The &block parameter that may be making you scratch your head is simply the syntax used to define a blocks name!

Lambdas

A lambda defines a block and it’s parameters, and also allows us to save it to a variable for later use. We can use lambdas as anonymous methods, or define a lambda like this:

greeting = -> { puts “Hello from a lambda!” }

…or like this:

greeting = lambda { puts “Hello from a lambda!” }

However, just like any other Ruby method, defining a lambda won’t run the code inside it. We need to use the call method for that:

greeting = -> { puts “Hello from a lambda!” }greeting.call# => “Hello from a lambda!”

We can also call a lambda with .(), [], and .===, but I personally feel that .call makes the code clearer and easier to understand. Lambdas can also take in arguments, and unlike procs (more on these further down the page), lambdas will throw an error if we pass the wrong number of arguments. Here is an example of a lambda defined with an argument:

greeting = ->(name) { puts “Hello, #{name}” }greeting.call(“Lebowski”)# => “Hello, Lebowski”

Procs

A proc (short for procedure) is essentially a block turned into an object of the Proc class. The syntax looks like (because it is) an instantiation of a class. We then execute a proc by calling the .call method on it. For example, we can assign a block to an instance of the Proc class, then assign that to a variable:

greeting = Proc.new { ‘Hello!’ }greeting.call# => ‘Hello!’

So here we created an instance of the Proc class with a block containing ‘Hello!’ and with the variable name greeting. We then use the .call method on the variable (which holds an instance of the Proc class) and see the return value of the block we passed in. Procs can also accept arguments that are passed into the .call method, like so:

greeting = Proc.new { |name| “Hello, #{name}!” }hello.call( “Lebowski” )# => “Hello, Lebowski!”

An interesting property of procs is that they don’t really care about the number of arguments. If you define a proc with one or many arguments and call it with none, it still runs!

There is much more that can be said about Ruby blocks, procs, and lambdas, but I hope this helps as a quick guide to get you familiar with the subject. Happy coding!

--

--