When are lambdas needed?

I have seen many tutorials on the Internet explaining where lambdas
CAN be used, such as clever multiplication functions, but when are
they actually NEEDED?

Sure, I can take a lambda and “pass it around” so to speak, but I can
call a function from anywhere too, right?

Can somebody give me an extremely useful, NOT complicated, example of
when lambdas are the absolute perfect solution to a problem?

Thanks!

On Thu, Apr 17, 2008 at 5:35 PM, Stedwick [email protected]
wrote:

Can somebody give me an extremely useful, NOT complicated, example of
when lambdas are the absolute perfect solution to a problem?

Every time you use a block in ruby you’re using a lambda implicitly.


Avdi

Home: http://avdi.org
Developer Blog: http://avdi.org/devblog/
Twitter: http://twitter.com/avdi
Journal: http://avdi.livejournal.com

Avdi G. wrote:

On Thu, Apr 17, 2008 at 5:35 PM, Stedwick [email protected] wrote:

Can somebody give me an extremely useful, NOT complicated, example of
when lambdas are the absolute perfect solution to a problem?

Every time you use a block in ruby you’re using a lambda implicitly.

Implicitly, but not really. I wonder, was the original question more
like “what are blocks for?” or “yes, I know what blocks are for, but why
are there also these Proc objects, which are instantiated with the
lambda construct?”

If the latter, then one answer is: when you need the program state that
is encapsulated in a block to persist outside of the method in which it
is used. For example, this happens in event-based frameworks: a setup
method in a client class registers lambdas as event handlers; the
framework doesn’t need to know the classes or methods of the client
class, hence loose coupling. As a bonus, these handlers can refer to
shared program state (local variables) in the setup method.

Joel VanderWerf wrote:

If the latter, then one answer is: when you need the program state that
is encapsulated in a block to persist outside of the method in which it
is used. For example, this happens in event-based frameworks: a setup
method in a client class registers lambdas as event handlers; the
framework doesn’t need to know the classes or methods of the client
class, hence loose coupling. As a bonus, these handlers can refer to
shared program state (local variables) in the setup method.

That’s probably the clearest illustration I’ve ever read of when to use
a block. Thank you.

I hope others chime in, too, as I couldn’t imagine programming without
the “implicit usage” of blocks (e.g. each, select, collect, etc.) but
have never used them for the purpose Joel described.

I just got “done” designing a delivery system, and although I’m happy
with it, I wonder if it could be done with blocks. (I re-read that
statement and it sounds stupid: ‘done with blocks’. I’ll simply trust
you see the absurdity of the statement and understand what I was trying
to say…)

On Apr 17, 2008, at 3:35 PM, Stedwick wrote:

Can somebody give me an extremely useful, NOT complicated, example of
when lambdas are the absolute perfect solution to a problem?

cache :index, :ttl => 42, :key => lambda{ request[‘important’] }

this is a class level method which says

“cache the index method, invalidating every 42 seconds, by using the
current request’s ‘important’ value from the query”

note that in this cast the lambda will be instance_eval’d - so when we
say ‘request’ here it will ultimately mean the current request

another example:

def each &block

 @list.each &block

end

here we need to have captured the calling block’s scope in other to
relay it along to our internal @list object’s each method. it’s NOT
the case that we want the scope if the function for this lambda, what
we want is logic bound to the scope of the caller

lambda are perfect anytime you want a context sensitive result and
don’t want to code everything in one massive global scope.

a @ http://codeforpeople.com/

lambda are perfect anytime you want a context sensitive result and
don’t want to code everything in one massive global scope.

My problem with lambda’s is that I have a hard time to find a
real use case for them. I am not sure of some use case with
lambda {} that brings a definite advantage over i.e. just
using some special object or simple method.

2008/4/18, Marc H. [email protected]:

lambda are perfect anytime you want a context sensitive result and
don’t want to code everything in one massive global scope.

My problem with lambda’s is that I have a hard time to find a
real use case for them. I am not sure of some use case with
lambda {} that brings a definite advantage over i.e. just
using some special object or simple method.

Technically, you can replace every lambda with
an class and an instance thereof. The difference is that
the lambda is syntactically and semantically more lightweight.

To add another example, Rake tasks store away lambdas.

my_lib_version = "1.0.2"

task :tgz do
  sh "tar -czf my_lib-#{my_lib_version}.tgz lib"
end

Assuming a Ruby-like language without lambdas,
we’d get this “pure OO” Rakefile:

class TgzTask
  def initialize(version)
    @version = version
  end
  def execute
    sh "tar -czf my_lib-#@version.tgz lib"
  end
end

my_lib_version = "1.0.2"

task :tgz, TgzTask.new(my_lib_version)

All context we need in our method (local variables,
eventually the current “self”) has to be explicetely
passed to the constructor, which has to initialize
our object etc. Rake would loose all its appeal.

Stefan

“Stedwick” [email protected] wrote in message
news:[email protected]

Thanks!
One main use is precisely when you don’t need to pass anything around -
you
need a one-off function, and probably the function isn’t particularly
complicated. Typical examples are when supplying a code block to a sort,
group, map or filter function.

Are they needed? No. But then again, neither are subroutines or modules
or
for loops…

AHS

On Apr 17, 2008, at 6:47 PM, Marc H. wrote:

My problem with lambda’s is that I have a hard time to find a
real use case for them. I am not sure of some use case with
lambda {} that brings a definite advantage over i.e. just
using some special object or simple method.

a lambda is a special object - on that knows about every variable in
scope. have fun maintaining code that populates that object by hand :wink:

the entire point of lambdas is that the language already has a
scope. so, sure, you can cherry pick the required variables and
populate an object, but you can also make loops with GOTO - lambda is
merely an abstraction.

the ‘definite’ bit comes in because you don’t HAVE to do ANYTHING.
you simply write this code

sum = 0

list.each do |i|

sum += i

end

and you don’t have to write anything special, the environment is
captured, the code is evaulated in the captured context, but you don’t
have to build a special summing function that take i and a sum var.

so it ‘definitely’ is an advantage - that is unless you don’t happen
to think less code is advantageous over more…

cheers.

a @ http://codeforpeople.com/

the lambda expression came from the lisp community, it’s kind of
abstraction of procedures.
in oo languages it’s usually difficult to extend methods than extend
data structures.
ruby or other modern programming languages did a great job to mix them
together.
well , back to the topic, imo to fully understand the power of
lambda(or abstraction), one has to look into the lisp/scheme world :slight_smile:

On 4/17/08, Marc H. [email protected] wrote:

lambda are perfect anytime you want a context sensitive result and
don’t want to code everything in one massive global scope.

My problem with lambda’s is that I have a hard time to find a
real use case for them. I am not sure of some use case with
lambda {} that brings a definite advantage over i.e. just
using some special object or simple method.

Short answer: they are more more concise and convenient.

Ever use C++ STL? In this library a “functor” is a very important
concept
(for various comparators, visiting objects, etc). You make a functor by
defining a class with a primary method for functor’s functionality
(“operator()”). It might also have some state (possibly maintained
through
other methods) or references to things external to the functor.

In ruby, this type of thing is done with blocks and lambdas. But, it is
a
lot more concise and convenient. Because blocks/lambdas have access to
variables in the scope where they are defined (which can also be used to
create state), there shouldn’t be a need to create dedicated “functor”
classes.

I code in C++ everyday and miss the not having closures. From what I’ve
read, C++ will get closures (like ruby has had since day 1) in the next
release (C++0x).

Eric

On Thu, 17 Apr 2008 20:50:18 -0500, zuo peng wrote:

the lambda expression came from the lisp community, it’s kind of
abstraction of procedures.
in oo languages it’s usually difficult to extend methods than extend
data structures.
ruby or other modern programming languages did a great job to mix them
together. well , back to the topic, imo to fully understand the power of
lambda(or abstraction), one has to look into the lisp/scheme world :slight_smile:

Lambda comes from lambda calculus. The fact that LISP uses them is just
a
happy coincidence.

But let’s compare LISP and Ruby for a moment.

In LISP, any time you want to pass an unnamed ad-hoc function to another
function, you define it like (lambda (var1 var2) (code)), so you wind up
using the lambda macro a lot. You might have
(mapcar #’(lambda (x) (* x x)) '(1 2 3 4))
which returns
(1 4 9 16)

In Ruby, you do this kind of thing a lot too. Only we have syntactic
sugar that makes things a little nicer in many cases. The equivalent
code
to the LISP example is
[1 2 3 4].map{|x| x*x}
so you just used a lambda, but didn’t have to type the keyword.

There’s one thing to know though. Kernel#proc and Kernel#lambda have
slightly different semantics when it comes to the return, next, and
break
keywords. Kernel#lambda does things one way, and Kernel#proc or a bare
block do things the other way. So really, Ruby uses lambdas a lot (maybe
even more than LISP) but we just don’t use the term very much, mostly
because we’ve shortened the syntax.

On Apr 17, 2008, at 6:47 PM, Marc H. wrote:

My problem with lambda’s is that I have a hard time to find a
real use case for them

one more note

if you use

open(path){|fd| p fd.read}

array.each{|i| p i}

or

hash.each{|k,v| p k,v}

you’ve found a use for them :wink:

a @ http://codeforpeople.com/

On Thu, 17 Apr 2008 16:58:44 -0500, Joel VanderWerf wrote:

are there also these Proc objects, which are instantiated with the
lambda construct?"

If the latter, then one answer is: when you need the program state that
is encapsulated in a block to persist outside of the method in which it
is used. For example, this happens in event-based frameworks: a setup
method in a client class registers lambdas as event handlers; the
framework doesn’t need to know the classes or methods of the client
class, hence loose coupling. As a bonus, these handlers can refer to
shared program state (local variables) in the setup method.

There are about a zillion ways to get and use a Proc object in Ruby

def foo
yield 1
end

def bar &baz
#baz is a Proc object, and you can pass
#that proc object to another method that takes a block
foo &baz
end

a=lambda{|x| x*x}
#a is a Proc object

b=proc{|x| x*x}
#b is a Proc object

c=Proc.new{|x| x*x}
#c is a Proc object

c.call 2
=>4
#you can also use #call on a Proc object

c[2]
=>4
#or you can “index” it like an Array (which is just a synonym for #call)

The difference between lambda and the other ways of getting a Proc
object
is that lambda treats return, next, and break a little bit differently.

In other languages (specifically LISP) use of LAMBDA is the most common
way to create closures. In Ruby, it’s one of the rarest.

–Ken

Stedwick [email protected] writes:

I have seen many tutorials on the Internet explaining where lambdas
CAN be used, such as clever multiplication functions, but when are
they actually NEEDED?

Sure, I can take a lambda and “pass it around” so to speak, but I can
call a function from anywhere too, right?

Can somebody give me an extremely useful, NOT complicated, example of
when lambdas are the absolute perfect solution to a problem?

Lambdas are anonymous function.

As long as you can give a name to all the functions, they’re not
needed, you can just define (ie. name) a function, and give that
function by name instead of using lambda.

But that’s the very point! One gets fed up in having to come with
names for ALL the little functions we can encounter in a program.

Like if you went on a road, and gave a name to all the little peebles
you encounter, keeping with you a picture of each peeble with the
associated (unique!) name in your notebook. What a big useless
notebook!

Also, lambdas (closures actually) are equivalent to classes (objects).
So, as long as you can write a class (give it a name!), and
instanciate an object, everywhere you would use lambdas, they’re not
needed. But what a burden!

Compare:


def example
array=[1,2,3,4]
array.each{|i| print i," -> “,i+i,”\n" }
array.each{|i| print i," -> “,i*i,”\n" }

:done
end

vs.


def printDouble(i)
print i," -> “,i+i,”\n"
end
def printSquare(i)
print i," -> “,i*i,”\n"
end

class Array
def callForEach(f)
for i in 0…self.size()-1 do
f.call(self[i])
end
end
end
def example
array=[1,2,3,4]
array.callForEach(method(:printDouble))
array.callForEach(method(:printSquare))
:done
end

and compare:


def example
k=42
array=[1,2,3,4]
array.each{|i| print i," -> “,i+k,”\n" }
array.each{|i| print i," -> “,i*k,”\n" }
:done
end

vs.


class Adder
def initialize(k)
@k=k
end
def run(i)
print i," -> “,[email protected],”\n"
end
end

class Multiplier
def initialize(k)
@k=k
end
def run(i)
print i," -> “,i*@k,”\n"
end
end

class Array
def sendRunWithEach(o)
for i in 0…self.size()-1 do
o.run(self[i])
end
end
end

def example
k=42
array=[1,2,3,4]
array.sendRunWithEach(Adder.new(k))
array.sendRunWithEach(Multiplier.new(k))
:done
end

So if you have a lot of time, a lot of memory, and a lot of fingers,
perhaps you can do without lambda, but us poor mortals just need it.

Ken B. wrote:

There are about a zillion ways to get and use a Proc object in Ruby

def foo
yield 1
end

There’s no Proc object involved in this case. For this reason, it’s
generally more efficient to use yield rather than &block, if possible in
the context of your program.

http://groups.google.com/group/ruby-talk-google/browse_thread/thread/1ba144ea7d8fc85d

Hi –

On Fri, 18 Apr 2008, Ken B. wrote:

The difference between lambda and the other ways of getting a Proc object
is that lambda treats return, next, and break a little bit differently.

It’s actually a difference between lambda and proc (which are
synonyms), on the one hand, and Proc.new on the other:

irb(main):009:0> lambda { return }.call
=> nil
irb(main):010:0> proc { return }.call
=> nil
irb(main):011:0> Proc.new { return }.call
LocalJumpError: unexpected return

Since it’s a bit confusing to have proc and Proc.new be different,
this has been changed in 1.9: proc and Proc.new are the same in 1.9,
and lambda is different.

(I still have no idea how to memorize which is which.)

David

On Fri, Apr 18, 2008 at 6:43 AM, David A. Black [email protected]
wrote:

It’s actually a difference between lambda and proc (which are
synonyms), on the one hand, and Proc.new on the other:

irb(main):009:0> lambda { return }.call
=> nil
irb(main):010:0> proc { return }.call
=> nil
irb(main):011:0> Proc.new { return }.call
LocalJumpError: unexpected return

Another difference between lambdas and procs, is that procs are less
strict about arity when they are called.
1: p = Proc .new {|x,y| [x,y]}
2: l = lambda {|x,y| [x, y]}
3:
4: p.call(1) # => [1, nil]
5: l.call # =>

~> -:5: wrong number of arguments (0 for 2) (ArgumentError)

~> from -:5:in `call’

~> from -:5

procs are invoked using the same semantics as a yield, which acts like
parallel assignment with nils being provided for missing arguments.

lambdas are invoked using the same semantics as a message send.

Since it’s a bit confusing to have proc and Proc.new be different,
this has been changed in 1.9: proc and Proc.new are the same in 1.9,
and lambda is different.

(I still have no idea how to memorize which is which.)

Thinking about this a bit, I think that the basic rule is that procs
act like blocks, in that:

arguments are passed to them using yield semantics
and
return effects a return from the activation of the code containing
the source of the block
break breaks out of the block into the activation of the code
containing the source of the block

Lambdas act like methods in that:

arguments are passed to them using method call semantics
and
return effects a return from the body of the lambda
break breaks out of the body of the lambda, back to the caller,
effectively becoming a return

So a double mnemonic might be:

proc rhymes with block
lambda and method both have and m while proc does not.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

On Fri, 18 Apr 2008 06:35:08 +0900
Stedwick [email protected] wrote:

Thanks!

How about using lambda as representing recursive type and
implemeting lazy evaluation in easygoing way.

class Natural
def initialize
@succ = lambda {Natural.new}
end

def take(maximum)
[1] + if maximum == 1
[]
else
@succ.call.take(maximum - 1)
end
end

def accumulate(num, result = 0)
if num == 0
result
else
accumulate(num - 1, result + 1)
end
end

def summate(maximum)
if maximum == 1
1
else
accumulate(maximum) + summate(maximum - 1)
end
end

def filter(index = 1,result = [], &block)
num = accumulate(index)
if yield(num) == true
result << num
filter(index + 1,result, &block)
else
result
end
end
end

irb(main):040:0> n = Natural.new
#<Natural:0xb7a970ec @succ=#Proc:[email protected]:3(irb)>

irb(main):041:0> n.take(100)
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1]

irb(main):042:0> n.accumulate(100)
100

irb(main):043:0> n.filter {|i| i < 10}
[1, 2, 3, 4, 5, 6, 7, 8, 9]

irb(main):045:0> n.summate(100)
5050

On Fri, 18 Apr 2008 05:43:49 -0500, David A. Black wrote:

irb(main):009:0> lambda { return }.call => nil
irb(main):010:0> proc { return }.call => nil
irb(main):011:0> Proc.new { return }.call LocalJumpError: unexpected
return

Since it’s a bit confusing to have proc and Proc.new be different, this
has been changed in 1.9: proc and Proc.new are the same in 1.9, and
lambda is different.

(I still have no idea how to memorize which is which.)

That’s why I tried to be intentionally vague about the differences, but
I
guess I wasn’t vague enough. Thanks everybody for filling in the
details.

–Ken

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs