Blocs, procs and lambdas in Ruby
Can you repeat please?
July 21st, 2015
Blocks, procs and lambdas are different types of closures in Ruby. In human language it simply refers to ways of repeating code. Blocks are usually well understood but procs and lambdas can be more mysterious. Hopefully this little explanation will help.
Blocs
They allow us to apply a specific code to a series of elements. They are recognizable under 2 forms, using {} or do…end.
array = [1, 2, 3, 4] array.cycle do |n| n*2 end # => [1, 4, 6, 8]
So, what happens here?
- First, we send the cycle method to an Array with a block of code (you remember the cycle method, right?)
- The code block interacts with a variable used within the cycle method (n in this case) and multiple it by 2.
- Each element inside the array is now doubled.
Procs
Blocs are great but what if we want to use the same bloc in several parts of a well-respected DRY code? We use procs! Procs are like blocks but can be saved and reused later in the code.
array = [1, 2, 3, 4] p = Proc.new { |n| puts n*2 } array.each(&p) # => [1, 4, 6, 8]
So, what happens here?
- First, we create a proc using Proc.new and write the block to be saved.
- The proc is then called on a method using &p.
- Each element inside the array is now doubled.
Lambdas
Procs and lambdas are very similar and are often used interchangeably. There are 2 main differences between both. First, procs do not check for the number of arguments when lambdas do, here is how it looks:
lam = lambda { |x| puts x } proc = Proc.new { |x| puts x } lam.call(1) # prints out 1 proc.call(1) # prints out 1 lam.call # ArgumentError: wrong number of arguments (0 for 1) proc.call # returns nil lam.call(1,2,3) # ArgumentError: wrong number of arguments (3 for 1) proc.call(1,2,3) # prints out 1 and forgets about the extra arguments
The second difference is that procs and lambdas treat return differently. While proc return will only work at the first method and return the value provided, lambdas will return their value and continue through the rest of the code.
def lambda lambda { return "Block string" }.call return "method is finished" end def proc Proc.new { return "Block string"}.call return "method is finished" end puts lambda # => Block string puts proc # => method is finished
This second difference makes procs more difficult to work with than lambdas, Ruby experts usually recommend working with the latter. I’m writing about these concepts as I’m learning about them, so as usual any feedback is more than welcome!