Assaph Mehr
1/6/2005 11:37:00 PM
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