PHWinfo banniere

Titres
PORTAIL ANNUAIRE ARTICLES COMPARATEUR HÉBERGEURS DEVIS FORUMS RÉDUCTEUR D'URL
Précédent   PHWinfo > Autres forums > Forum Programmation & Conception > comp.lang.ruby > using lambda, binding happens immediately?
S'inscrire FAQ Membres Recherche Messages du jour Marquer les forums comme lus
using lambda, binding happens immediately?

Réponse
 
LinkBack Outils de la discussion
Vieux 19/11/2007, 21h09   #1
Sam Larbi
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut using lambda, binding happens immediately?

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

  Réponse avec citation
Vieux 20/11/2007, 12h45   #2
Robert Klemme
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: using lambda, binding happens immediately?

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

  Réponse avec citation
Vieux 20/11/2007, 15h07   #3
Sam Larbi
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: using lambda, binding happens immediately?

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

  Réponse avec citation
Vieux 20/11/2007, 15h27   #4
Robert Klemme
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: using lambda, binding happens immediately?

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

  Réponse avec citation
Vieux 20/11/2007, 16h11   #5
Sam Larbi
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: using lambda, binding happens immediately?

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
>
>


  Réponse avec citation
Vieux 20/11/2007, 16h20   #6
Robert Klemme
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: using lambda, binding happens immediately?

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

  Réponse avec citation
Réponse


Outils de la discussion

Règles de messages
Vous ne pouvez pas créer de nouvelles discussions
Vous ne pouvez pas envoyer des réponses
Vous ne pouvez pas envoyer des pièces jointes
Vous ne pouvez pas modifier vos messages

Les balises BB sont activées : oui
Les smileys sont activés : oui
La balise [IMG] est activée : oui
Le code HTML peut être employé : non
Trackbacks are oui
Pingbacks are oui
Refbacks are oui


Fuseau horaire GMT +1. Il est actuellement 19h14.


Édité par : vBulletin® version 3.7.3
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.2.0 RC5 Tous droits réservés.
Version française #16 par l'association vBulletin francophone
PHWinfo est un site Éducation Sans Frontières ©2000-2008
Ad Management by RedTyger
©Tous droits réservés par les parties respectives
Page generated in 0,20581 seconds with 14 queries