|
|
|
|
||||||
![]() |
|
|
LinkBack | Outils de la discussion |
|
|
#1 |
|
Messages: n/a
Hébergeur: |
Note: parts of this message were removed by the gateway to make it a legal Usenet post.
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 Larbi |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
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 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 -- use.inject do |as, often| as.you_can - without end |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
Note: parts of this message were removed by the gateway to make it a legal Usenet post.
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. > > 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 Larbi |
|
|
|
#4 |
|
Messages: n/a
Hébergeur: |
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. $ 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 |
|
|
|
#5 |
|
Messages: n/a
Hébergeur: |
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 > > |
|
|
|
#6 |
|
Messages: n/a
Hébergeur: |
2007/11/20, Sam Larbi <slarbi@gmail.com>:
> 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. 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 -- use.inject do |as, often| as.you_can - without end |
|
![]() |
| Outils de la discussion | |
|
|