From: "David A. Black" Date: 2008-03-22T02:37:42+09:00 Subject: Re: dynamically defining a method on an instance that references vars in enclosing scope? 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: 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.) > 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!