Blocks, Procs, and Lambdas in Ruby

Blocks, Procs, and Lambdas in Ruby

Blocks, Procs, and Lambdas are Ruby’s approach to closures. Let’s start with Blocks.

Blocks

Blocks are any sort of anonymous function that can be passed into methods. The’re the sections of code encapsulated between either braces {} or do...end syntax. In short: you’ve probably used them a lot before.

They can be passed to functions as a &block argument (although the word “block” is purely conventional). Eg:

    def powers_of_twoifier(arr, &block)
      [1,2,4,8,16].each do |i|
        arr.push(block.call(i))
      end
    end

    results = []
    powers_of_twoifier(results) do |arg|
      arg * 2
    end # results = [2, 4, 8, 16, 32]

Blocks can also use yield instead of block.call. The difference is that you don’t need to specify &block in the argument list, it is called implicitly. This is convenient, but if you need to (for example) assign interim values to block within the method calling it, you’ll obviously want to be able to call it explicitly

Procs & Lambdas

Procs and Lambdas are both blocks that can be assigned to a variable. Eg:

def mathifier(arr, lambda)
    res = []
    arr.each do |i|
      res.push lmb.call(i)
    end
    return res
end

result = [1, 2, 4, 8, 16]
my_lambda = lambda { |i| i * 2}
doubled = mathifier(result, my_lambda) # result = [2, 4, 8, 16, 32]

Procs are very similar to lambdas, except:

  • Lambdas enforce argument count, whereas procs will set unassigned arguments to nil, and simply drop excess arguments
  • Calling return in a lambda stops processing of the lambda block, but not the underlying function/code. Calling return in a proc stops both the lambda and the function its nested in

Leave a Comment

Your email address will not be published. Required fields are marked *