# What's wrong with lambda and class

**URL:** <https://www.ruby-forum.com/t/whats-wrong-with-lambda-and-class/162143>\
**Category:** Ruby\
**Created:** [March 6, 2009, 6:30am UTC](https://www.ruby-forum.com/t/whats-wrong-with-lambda-and-class/162143 "2009-03-06T06:30:53Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![ivanstorck](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/e99b99/32.png) [@ivanstorck](https://www.ruby-forum.com/u/ivanstorck)\
**Post date:** [March 6, 2009, 6:30am UTC](https://www.ruby-forum.com/t/whats-wrong-with-lambda-and-class/162143/1 "2009-03-06T06:30:53Z")

</div>

Code:

def call\_block(&c)  
c.call  
end

def yield\_block(&c)  
yield  
end

def lambda\_and\_call  
c = lambda { return 1 }  
call\_block(&c) + 1  
end

def lambda\_and\_yield  
c = lambda { return 1 }  
yield\_block(&c) + 1  
end

def proc\_new\_and\_call  
c = Proc.new { return 1 }  
call\_block(&c) + 1  
end

def proc\_new\_and\_yield  
c = Proc.new { return 1 }  
yield\_block(&c) + 1  
end

[:lambda\_and\_call, :lambda\_and\_yield, :proc\_new\_and\_call,  
:proc\_new\_and\_yield].each {|m| puts â€œ#{m}: #{send(m)}â€}

Result:

lambda\_and\_call: 2  
lambda\_and\_yield: 1  
proc\_new\_and\_call: 1  
proc\_new\_and\_yield: 1  
Why 2?

---

<div class="post-metadata">

**Author:** ![ivanstorck](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/e99b99/32.png) [@ivanstorck](https://www.ruby-forum.com/u/ivanstorck)\
**Post date:** [March 6, 2009, 6:31am UTC](https://www.ruby-forum.com/t/whats-wrong-with-lambda-and-class/162143/2 "2009-03-06T06:31:42Z")

</div>

Sorry the topic is “lambda and call”

---

<div class="post-metadata">

**Author:** ![ivanstorck](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/e99b99/32.png) [@ivanstorck](https://www.ruby-forum.com/u/ivanstorck)\
**Post date:** [March 6, 2009, 12:12pm UTC](https://www.ruby-forum.com/t/whats-wrong-with-lambda-and-class/162143/3 "2009-03-06T12:12:14Z")

</div>

All fully explained at  
[http://innig.net/software/ruby/closures-in-ruby.rb](http://innig.net/software/ruby/closures-in-ruby.rb)

But in summary, the key difference between Proc/block and lambda is that  
return within a Proc/block returns from method it was invoked within,  
whereas return within a lambda just returns from the lambda itself.

---

<div class="post-metadata">

**Author:** ![ivanstorck](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/e99b99/32.png) [@ivanstorck](https://www.ruby-forum.com/u/ivanstorck)\
**Post date:** [March 6, 2009, 12:22pm UTC](https://www.ruby-forum.com/t/whats-wrong-with-lambda-and-class/162143/4 "2009-03-06T12:22:31Z")

</div>

Actually, the question for me was “why 1?” in your second case. Passing  
a lambda as a block argument to a method is an odd thing to do; I  
believe it is being coerced to a block as if you did Proc.new(&c).

Maybe this makes it clearer:

def call\_block(&c)  
c.call  
end

def lambda\_and\_call  
c = lambda { return 1 }  
call\_block(&c) + 1 # the lambda returns 1  
end

p lambda\_and\_call

def yield\_block(&c)  
yield  
end

def lambda\_and\_yield  
c = lambda { return 1 }  
x = yield\_block(&c) # the entire method returns 1  
STDERR.puts “This line is not reached!”  
x + 1  
end

p lambda\_and\_yield

---

<div class="post-metadata">

**Author:** ![ivanstorck](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/e99b99/32.png) [@ivanstorck](https://www.ruby-forum.com/u/ivanstorck)\
**Post date:** [March 7, 2009, 3:57am UTC](https://www.ruby-forum.com/t/whats-wrong-with-lambda-and-class/162143/5 "2009-03-07T03:57:05Z")

</div>

On Fri, Mar 6, 2009 at 3:45 AM, lasitha [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> 03\> end  
> definitive on this yet.  
> The idea that it has to do with yield is basically right, though I’d  
> describe it as having to do with blocks as distinct from instances of  
> class Proc (procs or lambdas).

When you yield to a block attached to a function – which, you must  
keep in mind, isn’t a proc or a lambda or even a normal Ruby object at  
all, its a different beast entirely though you can call a method with  
the method(&proc) notation to send a Proc instance (proc or lambda) to  
be wrapped in a block\* – it behaves like a proc (that is an object  
created with Proc.new {…} in any version of ruby, and also proc  
{…} in Ruby 1.9.x.) Both “lambda\_and\_yield” and “proc\_and\_yield”,  
therefore, aren’t yielding to lambdas or procs, the methods yield to a  
block in both cases, so the behavior is the same, and the same as it  
would be if you attached a block to the method call directly instead  
of supplying a Proc instance to wrap in a block by calling with the  
method(&proc) notation.

- I’ve often seen it described as “treated as” or “converted to” a  
block, but its clear that it retains its identity, since if you define  
a method with def method(&block) to make a passed Proc instance or  
block accessible within the method body as a Proc instance, the local  
Proc instance is still a lambda if you passed in a lambda, which  
suggests to me that a call to the Proc instance gets wrapped in a  
block if the method doesn’t use the &block argument pattern to get it  
as a Proc instance. The Pickaxe (2nd Ed.) does discuss the behavior of  
blocks, procs (which it calls “raw procs”), and lambdas in quite some  
detail, on pp. 356-360.

---

<div class="post-metadata">

**Author:** ![ivanstorck](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/e99b99/32.png) [@ivanstorck](https://www.ruby-forum.com/u/ivanstorck)\
**Post date:** [March 6, 2009, 12:48pm UTC](https://www.ruby-forum.com/t/whats-wrong-with-lambda-and-class/162143/6 "2009-03-06T12:48:14Z")

</div>

On Fri, Mar 6, 2009 at 4:50 PM, Brian C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> Actually, the question for me was “why 1?” in your second case. Passing  
> a lambda as a block argument to a method is an odd thing to do; I  
> believe it is being coerced to a block as if you did Proc.new(&c).

That’s what i’m trying to figure out, too.  
If the lambda is being coerced, it isn’t being honest about it:

01\> def is\_lambda?(&closure)  
02\> closure.lambda?  
03\> end  
04\> is\_lambda? &(Proc.new { })  
 → false  
05\> is\_lambda? &(lambda { })  
 → true

Perhaps it has more to do with rules around yield (or it’s  
implementation)?

All i’ve dug up so far is this (unanswered) thread:  
[http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/22634](http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/22634)

Been scanning the Pickaxe and Flannagan/Matz but haven’t seen anything  
definitive on this yet.

FWIW,  
lasitha

---

<div class="post-metadata">

**Author:** ![ivanstorck](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/e99b99/32.png) [@ivanstorck](https://www.ruby-forum.com/u/ivanstorck)\
**Post date:** [March 7, 2009, 9:44am UTC](https://www.ruby-forum.com/t/whats-wrong-with-lambda-and-class/162143/7 "2009-03-07T09:44:33Z")

</div>

Christopher D. wrote:

> When you yield to a block attached to a function – which, you must  
> keep in mind, isn’t a proc or a lambda or even a normal Ruby object at  
> all, its a different beast entirely though you can call a method with  
> the method(&proc) notation to send a Proc instance (proc or lambda) to  
> be wrapped in a block\* – it behaves like a proc (that is an object  
> created with Proc.new {…} in any version of ruby, and also proc  
> {…} in Ruby 1.9.x.) Both “lambda\_and\_yield” and “proc\_and\_yield”,  
> therefore, aren’t yielding to lambdas or procs, the methods yield to a  
> block in both cases

But the object\_id is the same, so it’s not wrapped in a “block” object.  
And neither, I think, is it mutated. There is “is\_lambda?” in 1.9, but  
no “is\_block?”

> which  
> suggests to me that a call to the Proc instance gets wrapped in a  
> block if the method doesn’t use the &block argument pattern to get it  
> as a Proc instance.

But the only way to get hold of the block argument without &block is to  
use yield. So it is equivalent to say that yield has special semantics.

The Pickaxe (2nd Ed.) does discuss the behavior of

> blocks, procs (which it calls “raw procs”), and lambdas in quite some  
> detail, on pp. 356-360.

It’s somewhat incomplete. p357-p358

"There are three ways of converting a block into a Proc object:

1. By passing a block to a method whose last parameter is prefixed with  
an ampersand. That parameter will receive the block as a Proc object"

But it doesn’t say what happens if you pass a lambda, using the &  
notation at the caller.

It says that a block is not an object at all, and it goes on to make a  
distinction between two types of real objects: a “raw proc” and a  
“lambda”, which are the two flavours of Proc object.

I’m not sure whether it makes much sense to consider a block as a third  
class of entity, which is not an object at all. If I do

def receiver(&blk)  
STDERR.puts blk.object\_id  
end

foo = lambda { “Whoa” }  
STDERR.puts foo.object\_id  
receiver(&foo)

then blk in receiver is exactly the same object as foo at the caller.
