From: Anders Borch Date: 2004-06-17T19:28:51+09:00 Subject: Re: Delayed Instantiation - delayed.rb is it just me, or could the same results come from this: class DelayedInstance def initialize(klass,*args) @klass = klass @args = args @object = nil end def method_missing(meth,*args,&block) @object = @klass.send(:new,*@args) if @object.nil? @object.send(meth,*args,&block) end end matt wrote: > Here's some code I wrote to delay object instantiation until an > object's methods are needed. If there's anything fooey about it, or > if there's a better version out there, please let me know :-) > > > > --begin-- > ######################################################################### > ######################################################################### > #### delayed.rb: Thunks for Object Insantiation > #### > #### Author: Matthew Maycock > #### > #### Email: _mr_bill_98@yahoo.com > #### > #### Date: June 16th, 2004 AD! > #### > #### > #### > #### Purpose: > #### > #### Delay instantiation of objects until needed. > #### > #### Overhead given by an extra indirection of dispatch > #### > #### Use at your own risk! > #### > #### > #### > #### License: > #### > #### The least restrictive license applicable to this software > #### > #### given that it was written in ruby and uses the ruby library. > #### > #### I don't really know that much about such things, so if there > #### > #### isn't anything in the way, consider this released under the > #### > #### public domain, free for all! > #### > ######################################################################### > ######################################################################### > > > > # Delay creation of an object until some method tries to use it. > class DelayedInstance < Object > def initialize(klass, *args) > @object = Object.new > ivars = Object.instance_method(:instance_variables) > ieval = Object.instance_method(:instance_eval) > iclss = Object.instance_method(:class) > inspt = Object.instance_method(:inspect) > > switched = @delayed_switched = false > > > switch = @delayed_switch = Proc.new { > raise "Already switched!" if switched > switched = @delayed_switched = true > @object = klass.send(:new, *args) > } > > delayed_self = self > @object.instance_eval { > @delayed_parent = delayed_self > @delayed_switch = switch > @delayed_added = false > @delayed_eval = ieval > } > > [:==, :===, :=~, :__id__, :__send__, :class, :clone, :display, > :dup, :eql?, :equal?, :extend, :freeze, :frozen?, :hash, :id, > :inspect, :instance_eval, :instance_of, :instance_variable_get, > :instance_variable_set, :instance_variables, :is_a?, :kind_of?, > :method, :methods, :new, :nil?, :object_id, :private_methods, > :protected_methods, :public_methods, :remove_instance_variable, > :respond_to?, :send, :singleton_method_added, > :singleton_method_removed, :singleton_method_undefined, > :singleton_methods, :taint, > :tainted?, :to_a, :to_s, :type, :untaint].each {|sym| > eval <<-END_EVAL > def @object.#{sym.to_s}(*args, &block) > return super(*args, &block) unless @delayed_added > parent = @delayed_parent > @delayed_switch[] > obj = @delayed_eval.bind(parent).call { @object } > obj.send(#{sym.inspect}, *args, &block) > end > END_EVAL > } > > Object.instance_method(:instance_eval).bind(@object).call > {@delayed_added = true} > end > > def method_missing(sym, *args, &block) > @delayed_switch[] unless @delayed_switched > @object.send(sym, *args, &block) > end > end > > [:==, :===, :=~, :__id__, :__send__, :class, :clone, :display, :dup, > :eql?, :equal?, :extend, :freeze, :frozen?, :hash, :id, > :inspect, :instance_eval, :instance_of, :instance_variable_get, > :instance_variable_set, :instance_variables, :is_a?, :kind_of?, > :method, :methods, :new, :nil?, :object_id, :private_methods, > :protected_methods, :public_methods, :remove_instance_variable, > :respond_to?, :send, :singleton_method_added, > :singleton_method_removed, :singleton_method_undefined, > :singleton_methods, :taint, > :tainted?, :to_a, :to_s, :type, :untaint].each {|sym| > DelayedInstance.module_eval <<-END_EVAL > def #{sym.to_s}(*args, &block) > @object.send(#{sym.inspect}, *args, &block) > end > END_EVAL > } > > > > if __FILE__ == $0 then > > class Test > def initialize(index) > $stdout.puts "Something that takes a thousand hours..." > @index = index > end > > def display > $stdout.puts @index > end > end > > data = (1..10).map {|i| DelayedInstance.new(Test, i)} > data.each {|d| d.display} > > $stdout.puts > foo = DelayedInstance.new(Test, 1000) > foo.instance_eval { > $stdout.puts "Instance Eval!" > @santa = 100 > } > > $stdout.puts foo.instance_variables.inspect > $stdout.puts foo.instance_eval {@santa} > end > > =begin > ### ruby -v: ruby 1.8.1 (2003-12-25) [i386-mswin32] > # OUTPUT > Something that takes a thousand hours... > 1 > Something that takes a thousand hours... > 2 > Something that takes a thousand hours... > 3 > Something that takes a thousand hours... > 4 > Something that takes a thousand hours... > 5 > Something that takes a thousand hours... > 6 > Something that takes a thousand hours... > 7 > Something that takes a thousand hours... > 8 > Something that takes a thousand hours... > 9 > Something that takes a thousand hours... > 10 > > Something that takes a thousand hours... > Instance Eval! > ["@index", "@santa"] > 100 > =end >