# Using lambda, binding happens immediately?

**URL:** <https://www.ruby-forum.com/t/using-lambda-binding-happens-immediately/120699>\
**Category:** Ruby\
**Created:** [November 19, 2007, 10:10pm UTC](https://www.ruby-forum.com/t/using-lambda-binding-happens-immediately/120699 "2007-11-19T22:10:16Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![sam](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/5f9b8f/32.png) [@sam](https://www.ruby-forum.com/u/sam)\
**Post date:** [November 19, 2007, 10:10pm UTC](https://www.ruby-forum.com/t/using-lambda-binding-happens-immediately/120699/1 "2007-11-19T22:10:16Z")

</div>

I have this code:

require ‘test/unit’  
require ‘leapyear’  
class LeapYearTest \< Test::Unit::TestCase  
def setup  
@ly = LeapYear.new  
end  
def LeapYearTest.generate\_tests  
filename = “testdata.dat”  
file = File.new(filename, “r”)  
file.each\_line do |line|  
year, is\_leap = line.split;  
code = lambda { assert\_equal(is\_leap.downcase==“true”,  
@ly.isleap?(  
year.to\_i)) }  
define\_method(“test\_isleap\_” + year, code)  
end  
file.close  
end  
end

What I want to know is why when I use define\_method(“name”) {block;}  
instead  
of define\_method(“name”, lambda{block}) the binding seems to happen  
later  
(after the each\_line loop)?

Is there a reason behind that?

Thanks,  
Sammy L.

---

<div class="post-metadata">

**Author:** ![sam](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/5f9b8f/32.png) [@sam](https://www.ruby-forum.com/u/sam)\
**Post date:** [November 20, 2007, 1:46pm UTC](https://www.ruby-forum.com/t/using-lambda-binding-happens-immediately/120699/2 "2007-11-20T13:46:26Z")

</div>

2007/11/19, Sam L. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> ```
> filename = "testdata.dat"
> 
> ```
> 
> What I want to know is why when I use define\_method(“name”) {block;} instead  
> of define\_method(“name”, lambda{block}) the binding seems to happen later  
> (after the each\_line loop)?
> 
> Is there a reason behind that?

I’m not sure I understand you but why don’t you just do

define\_method(“test\_isleap\_” + year) do  
assert\_equal(is\_leap.downcase==“true”, @ly.isleap?(year.to\_i))  
end

Btw, I’d also use the block form of File.open because it is more  
robust than the idiom you are using.

Kind regards

robert

---

<div class="post-metadata">

**Author:** ![sam](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/5f9b8f/32.png) [@sam](https://www.ruby-forum.com/u/sam)\
**Post date:** [November 20, 2007, 4:08pm UTC](https://www.ruby-forum.com/t/using-lambda-binding-happens-immediately/120699/3 "2007-11-20T16:08:34Z")

</div>

Thanks Robert,

I have some more questions / responses below.

On Nov 20, 2007 6:45 AM, Robert K. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> > def LeapYearTest.generate\_tests  
> > end
> 
> I’m not sure I understand you but why don’t you just do

Well, the problem is that attaching the block uses only the last “year”  
to  
be processed in the loop, never the appropriate one.

> define\_method(“test\_isleap\_” + year) do  
> assert\_equal(is\_leap.downcase==“true”, @ly.isleap?(year.to\_i))  
> end

My understanding is that this would do the same as define\_method(…) {  
…}, so I would expect to have the same problem.

Basically, lets say the file testdata.dat has the following lines:

2000 true  
2004 true  
2001 false

Then running the code above (with leapyear class defined as well) would  
use  
2001 as the date for each of the tests if I used the block attachment as  
opposed to passing through the arguments after using lambda (although  
the  
tests would be named correctly).

So basically, It would generate the following:

test\_isleap2000 → but the date inside is 2001  
test\_isleap2004 → but the date inside is 2001  
test\_isleap2001 → the test is correct

Then, if I use lambda, the tests are all correct.

Does that make any more sense?

> Btw, I’d also use the block form of File.open because it is more  
> robust than the idiom you are using.

Thanks for pointing that out - I do like how it closes for you, so you  
don’t  
have to remember to do it.

Sammy L.

---

<div class="post-metadata">

**Author:** ![sam](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/5f9b8f/32.png) [@sam](https://www.ruby-forum.com/u/sam)\
**Post date:** [November 20, 2007, 4:29pm UTC](https://www.ruby-forum.com/t/using-lambda-binding-happens-immediately/120699/4 "2007-11-20T16:29:07Z")

</div>

2007/11/20, Sam L. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> > > ```
> > > year, is_leap = line.split;
> > > 
> > > ```
> > > 
> > > What I want to know is why when I use define\_method(“name”) {block;}  
> > > Well, the problem is that attaching the block uses only the last “year” to  
> > > be processed in the loop, never the appropriate one.

Then you are using “year” outside the block as well and the code you  
have shown is not the code you actually run.

$ ruby /cygdrive/c/sc.rb.txt  
foo  
bar  
16:23:16 $ cat /cygdrive/c/sc.rb.txt  
class Foo  
def self.create(words)  
words.each do |w|  
define\_method(“test\_#{w}”) { puts w }  
end  
end  
end  
Foo.create %w{foo bar}  
Foo.new.test\_foo  
Foo.new.test\_bar  
16:23:28 $ ruby /cygdrive/c/sc.rb.txt  
bar  
bar  
16:24:18 $ cat /cygdrive/c/sc.rb.txt  
class Foo  
def self.create(words)  
w = nil  
words.each do |w|  
define\_method(“test\_#{w}”) { puts w }  
end  
end  
end  
Foo.create %w{foo bar}  
Foo.new.test\_foo  
Foo.new.test\_bar  
16:24:19

> 2000 true  
> test\_isleap2000 → but the date inside is 2001  
> test\_isleap2004 → but the date inside is 2001  
> test\_isleap2001 → the test is correct
> 
> Then, if I use lambda, the tests are all correct.
> 
> Does that make any more sense?

I am afraid, no (see above).

Kind regards

robert

---

<div class="post-metadata">

**Author:** ![sam](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/5f9b8f/32.png) [@sam](https://www.ruby-forum.com/u/sam)\
**Post date:** [November 20, 2007, 5:14pm UTC](https://www.ruby-forum.com/t/using-lambda-binding-happens-immediately/120699/5 "2007-11-20T17:14:30Z")

</div>

Robert,

On Nov 20, 2007 9:27 AM, Robert K. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> > > > I have this code:  
> > > > file = File.new(filename, “r”)  
> > > > end  
> > > > I’m not sure I understand you but why don’t you just do
> > 
> > Well, the problem is that attaching the block uses only the last “year”  
> > to  
> > be processed in the loop, never the appropriate one.
> 
> Then you are using “year” outside the block as well and the code you  
> have shown is not the code you actually run.

I tried your code and as you know, it works fine. I even reconstructed  
the  
tests for it, and it still worked fine.

The problem I had was over a year old, so I wonder if this was only the  
case  
in an older version of Ruby. (Can anyone confirm or deny that?) I’m  
certain I had the problem before, but obviously we cannot reproduce it  
in  
this similar case.

If I can find the old code for the LeapYear class I’ll give it a shot  
and  
get back to you.

Sammy L.

---

<div class="post-metadata">

**Author:** ![sam](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/5f9b8f/32.png) [@sam](https://www.ruby-forum.com/u/sam)\
**Post date:** [November 20, 2007, 5:23pm UTC](https://www.ruby-forum.com/t/using-lambda-binding-happens-immediately/120699/6 "2007-11-20T17:23:21Z")

</div>

2007/11/20, Sam L. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> > > On Nov 20, 2007 6:45 AM, Robert K. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)
> > > 
> > > > > ```
> > > > > @ly = LeapYear.new
> > > > > define_method("test_isleap_" + year, code)
> > > > > 
> > > > > ```
> > > > > 
> > > > > (after the each\_line loop)?  
> > > > > Then you are using “year” outside the block as well and the code you
> 
> If I can find the old code for the LeapYear class I’ll give it a shot and  
> get back to you.

IMHO even older Ruby version should behave the same, i.e. when the  
variable is used inside the block only then you get multiple copies of  
it and thus your created methods won’t share them.

Kind regards

robert
