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