From: itsme213 Date: 2005-01-08T02:46:27+09:00 Subject: Re: Ruby design question: lazy construction of object graph containing forward references Wow! Self-modifying code makes my head spin. It seems to almost do logical variable (1-way) unification. Could it be adapted to get the behavior I want below? x = Object.new; x.extend LazyForwardRef x.forward_ref(:foo) p x.foo #=> something for 'uninitialized' y = Object.new; y.extend LazyForwardRef y.forward_ref(:bar) p y.bar #=> something for 'uninitialized' x.foo = y.bar p x.foo #=> something for 'suspended/lazy' y.bar = 10 p y.bar #=> 10 p x.foo #=> 10 (or still 'suspended/lazy' if 10 is too difficult) x.resolve_ref(:foo) p x.foo #=> 10 Many thanks. "Assaph Mehr" wrote in message news:1105054617.978569.32830@f14g2000cwb.googlegroups.com... > Here's an implementation of lazy forward references. Notice that if you > assign to a variable before reading it, the previous lazy > initialization will be overwritten. > > __BEGIN CODE__ > class Object > def singleton_class > class << self; self; end > end > end > > module LazyForwardRef > def forward_ref(meth, &bl) > self.singleton_class.send :define_method, meth, lambda{ > self.singleton_class.send :define_method, meth, lambda { > self.singleton_class.send :attr_accessor, meth > instance_variable_set "@#{meth}", bl.call > } > return send(meth) > } > self.singleton_class.send :define_method, "#{meth}=", lambda{ > |args| > self.singleton_class.send :define_method, meth, lambda { > self.singleton_class.send :attr_accessor, meth > instance_variable_set "@#{meth}", *args > } > return send(meth) > } > end > end > > > require 'pp' > > x = Object.new > x.extend LazyForwardRef > > begin > p x.foo > rescue NoMethodError => detail > pp detail > pp [x, x.methods.sort - Object.instance_methods] > end > > > x.forward_ref(:foo) { Hash[1,2,3,4] } > pp [x, x.methods.sort - Object.instance_methods] > > p x.foo > pp [x, x.methods.sort - Object.instance_methods] > > x.foo = 'Something else' > pp x > > p x.foo > > puts "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n" > > y = Object.new > y.extend LazyForwardRef > > y.forward_ref(:bar) { [1,2,3,4] } > pp [y, y.methods.sort - Object.instance_methods] > y.bar= 10 > pp [y, y.methods.sort - Object.instance_methods] > p y.bar >