From: mutahhir hayat Date: 2008-03-22T02:55:11+09:00 Subject: Re: dynamically defining a method on an instance that references vars in enclosing scope? On Sat, Mar 22, 2008 at 1:37 AM, David A. Black wrote: > Hi -- > > On Sat, 22 Mar 2008, mutahhir hayat wrote: > > > >> I know that the problem is scope. That's why I suggested a way to > >> manipulate the scope :-) > >> > >> I definitely would not (and deliberately did not) throw a global > >> variable at it. Also, defining x inside MyClass doesn't help, because > >> that's also a different local scope. > > > > I wasn't sure, but running an intermix of your code with the original > > still would give the same error in irb. I wasn't advocating the use of > > globals, ( though, come to think about it, i do feel bad now even > > mentioning it :P) but I didn't consider that x wouldn't be usable. > > I don't see the error: Sorry, my bad, i rewrote it in my irb, and it validates your code. :) Must be getting to bed now, clock's slowing. > > irb(main):001:0> class Object > irb(main):002:1> def singleton_class > irb(main):003:2> class << self > irb(main):004:3> self > irb(main):005:3> end > irb(main):006:2> end > irb(main):007:1> end > => nil > irb(main):008:0> > irb(main):009:0* instance = Object.new > => # > irb(main):010:0> x = 1 > => 1 > irb(main):011:0> > irb(main):012:0* instance.singleton_class.class_eval { > irb(main):013:1* define_method("foo") { puts x } > irb(main):014:1> } > => # > irb(main):015:0> > irb(main):016:0* instance.foo > > 1 > > > :) I'm still getting used to this metaprogramming thing, but how did > > you change scope? In my view, the scope remains exactly same, you just > > allowed the method to be inserted into the object instance > > dynamically. > > That's the thing: I didn't change scope. The block that uses x (line > 013 above) is in the same scope as the line that defines x (010) -- at > least, in the same scope block-style. (Meaning: the block can see all > the locals that are already in scope.) > I get you, since the block passed to class_eval was defined in the same scope as x, it would be knowledgeable about it. But tell me, other than academic, won't this be really bad to use? Like, maybe you shadow some variable, and so on... I dunno, :P as i said, nearing my limit, so maybe i'm just jabbering here. But it was fun learning from you, glad to be on this list. Thanks. ( Although, according to my judgment (sorry if i'm wrong) of the level of the programmer by the nature of the question, i'm pretty sure we made the questioner scream ) :) See ya, MT > > > Anyways, simplest i found was: (swearing never to mention global again... :P) > > > > class MyClass > > attr_accessor :x > > #... or if you want you could do > > # def initialize(x); @x = x; end > > end > > > > instance = MyClass.new > > > > def instance.foo > > puts x > > end > > > > instance.x = 1 > > instance.foo > > > > > > would work. > > Yes, but you've shifted to instance variables. That's a more common > use case than the class_eval/define_method one, but they're both worth > knowing about. > > > > > David > > -- > Upcoming Rails training from David A. Black and Ruby Power and Light: > ADVANCING WITH RAILS, April 14-17 2008, New York City > CORE RAILS, June 24-27 2008, London (Skills Matter) > See http://www.rubypal.com for details. Berlin dates coming soon! > >