51

When should a lambda or proc be used? I have seen them described as anonymous functions, but I am struggling to understand this concept. I would appreciate any links to or examples of when you might use one in Ruby, but especially in Ruby on Rails.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Cameron
  • 4,181
  • 9
  • 36
  • 40

7 Answers7

44

http://augustl.com/blog/2008/procs_blocks_and_anonymous_functions/ has a run-down of what blocks/procs/lambdas are, how you can use them, and how they compare to functions in other languages. It definitely answers your question.

Do be aware that the last section 'A note on lambdas' mentions a point that is only true in Ruby 1.8 and changed in 1.9 - Ruby: Proc.new { 'waffles' } vs. proc { 'waffles' }

Community
  • 1
  • 1
August Lilleaas
  • 54,010
  • 13
  • 102
  • 111
12

I don't see where you make the distinction between Ruby on Rails and Ruby. If you're writing a Ruby on Rails application, you're writing Ruby code, so if it's useful in Ruby, it should be useful in Ruby on Rails.

Anyway, this article, Some Useful Closures in Ruby, should be helpful, as well as this: http://www.robertsosinski.com/2008/12/21/understanding-ruby-blocks-procs-and-lambdas/

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ehsanul
  • 7,737
  • 7
  • 33
  • 43
  • Good point. Some kind of cheat sheet that listed all built-in methods taking lambda could sort of make sense, but if you understand what a lambda is, you don't need such a cheat sheet. – August Lilleaas Aug 05 '09 at 14:18
11

What is lambda?

Try this with your irb.

lam = lambda { puts "Hello world"}
lam.class

#output is
=> Proc

lambda in ruby is also a instance of Proc class. lambdas are a different flavor of procs.

What is Proc?

Proc objects are blocks of code that have been bound to a set of local variables.

proc = Proc.new { puts "Hello World" }
proc.call

#output is
=> Hello World

What is the difference between a proc and lambda? Comparission will explain usecases

Lambdas check the number of arguments, while procs do not.

multiply = lambda { |x,y| x*y }
multiply.call(2,3)  #=>6
multiply.call(2)    #ArgumentError: wrong number of arguments (1 for 2)

multiply = Proc.new {|x| x*x}
multiply.call(2)    # =>4
multiply.call(2,3)  # =>4 (It ignore the second argument)

Lambdas and procs treat the ‘return’ keyword differently (Read the article below for example)

Read this great article for more details http://awaxman11.github.io/blog/2013/08/05/what-is-the-difference-between-a-block/

MadNik
  • 7,713
  • 2
  • 37
  • 39
9

It is a piece of code that allows you to pass around.

It is especially useful in named_scope, it allows to you do something like this:

named_scope :scoped_by_user, lambda {|user| {:conditions=>{:user_id=>user.id}}}

Say you have a Project model and you want to get all the projects for one particular user, you can do something like this:

Project.scoped_by_user(123)
ez.
  • 7,604
  • 5
  • 30
  • 29
7

Where I've seen Lambda used is in testing...

lambda do
    post :create, :user => @attr
end.should_not change(User, :count)

Lambda allows you to have that test at the end to make sure that the code executed in the lambda block doesn't change change the User count.

sudonim
  • 171
  • 1
  • 5
4

lambda is exceptionally useful in named_scope, so that you can pass parameters to named_scopes.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ErsatzRyan
  • 3,033
  • 1
  • 26
  • 30
2

Many validator options accept a lambda or Proc if the work is too simple to warrant a named function. For example, :if and :unless.

validates :thing, presence: true, unless: ->(obj) { obj.something? }

:message will accept a Proc for custom validator messages.

validates :terms, acceptance: {
    message: ->(person) "%{person.name} must accept our terms!"
}

Generally, lambdas (and callbacks in general) are useful as a lightweight way to allow more customization than a string or number allows, but without the user having to write a full class.

Schwern
  • 153,029
  • 25
  • 195
  • 336