Lambda, procs and ActiveRecord scopes - Part 1

Tags: ruby, lambda
Publish Date: 2016-06-19
Contents:
  1. The lambda method vs "stabby lambda" constructor ->(){}
  2. scope method within ActiveRecord(::Scoping::Named::ClassMethods)
  3. Differences between lambda and Proc

 

During a pair-programming session some time ago, while writing a rather long ActiveRecord scope, my coding-partner was asking me whether "it would work if we replace the curly braces {} with do / end".

scope :scope_name, -> (block-param1, block-param2 ){ some_invocation(block-param1).some_other_invocation(block-param2) }

I was a bit surprised when he asked this. As an experienced programmer with a strong acedemic background in CS, it should be clear to him that the curly braces were wrapping a code-block, right?

However, I can also see why my coding-partner was asking this:

  1. The stabby lambda's lack of explicity can create confusion.
  2. Many "Rails developers" simply follow code examples without looking seriously into the API. As a result, they don't know what they are doing.

 

The lambda method and "stabby lambda" constructor -> (){}

Both the lambda method and the "stabby lambda" produce the same result, so why are there two notations?

The reason is that, in Ruby versions older than 1.9, the interpreter had problems parsing lambda's that have block parameters with default values. The old interpreters could not figure out whether the second pipe (|) was a delimiter for block-parameters or a Bitwise OR operator:

# Cannot compile lambdas with block parameters that have default values
lambda { |a,b=1| puts a* b }

# No problems when block parameters have no default values
lambda { |a,b| puts a* b }
 => #<Proc:0x00007fd48490a7f8@(irb):5> 

As a result of this problem, the stabby lambda constructor has been added:

-> (a, b=0) { puts a * b }

However, this parsing problem has been solved from 1.9 and therefore the stabby lambda was no longer necessary. But in the meantime, it has created a cult following among Rails developers.

If you look at the Rails Guide for version 3.2 and before, you can see that they used to demonstrate scope with the lambda method. Then from version 4.0, for whatever reason, the Rails team has decided to demostrate the scope method with the stabby lambda constructor.

 

Pros and Cons of both notations

One reason why some prefer the stabby lambda, is that it is shorter than typing the word lambda.

However, in contrast to the lambda method, the "stabby lambda" constructor does not explicitly tell you that it is creating a lambda. As a result, when people follow the examples on Rails Guide (or elsewhere) with a stabby constructor, there is a chance that they are not aware of that they are actually creating a lambda.

In my opinion, even though lambda method takes more keystrokes, it still has the advantage of providing more clarity and explicity. Just imagine you being a new Ruby programmer, who has to perform a google search for "->(){} ruby" instead of "lambda ruby"!

In the next post, we will explore how the scope method within ActiveRecord uses lambda and blocks to define class methods and extends ActiveRecord::Relation objects.