Sammy Larbi
11/20/2007 4:12:00 PM
Note: parts of this message were removed by the gateway to make it a legal Usenet post.
Robert,
On Nov 20, 2007 9:27 AM, Robert Klemme <shortcutter@googlemail.com> wrote:
> 2007/11/20, Sam Larbi <slarbi@gmail.com>:
> > Thanks Robert,
> >
> > I have some more questions / responses below.
> >
> >
> > On Nov 20, 2007 6:45 AM, Robert Klemme <shortcutter@googlemail.com>
> wrote:
> >
> > > 2007/11/19, Sam Larbi <slarbi@gmail.com>:
> > > > 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?
> > >
> > > 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 Larbi
>
> $ 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
>
> > > 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?
>
> I am afraid, no (see above).
>
> Kind regards
>
> robert
>
> --
> use.inject do |as, often| as.you_can - without end
>
>