Hi, At Thu, 5 Oct 2006 08:18:24 +0900, Gavin Kistner wrote in [ruby-talk:218056]: > The Situation/Requirements > -------------------------- > A class has 2 different methods. > Each method needs a couple 'scratch' objects to perform its > calculations. > The methods call each other; they must not use the same scratch objects. > It is expensive to instantiate a scratch object. > It's not expensive to initialize an existing scratch object with data. > We like OOP coding, and want to call these as methods of a receiver. > > Wasteful Example: > class Foo > def c1 > tmp1 = ExpensiveObject.new > tmp2 = ExpensiveObject.new > # stuff involving tmp1/tmp2 > result = tmp1 + tmp2 + c2 > end > def c2 > tmp1 = ExpensiveObject.new > tmp2 = ExpensiveObject.new > # stuff involving tmp1/tmp2 > result = tmp1 + tmp2 > end > end Like this? $ ruby eo.rb 5 #<Foo::ExpensiveObject: 1> #<Foo::ExpensiveObject: 2> #<Foo::ExpensiveObject: 3> #<Foo::ExpensiveObject: 4> #<Foo::ExpensiveObject: 5> [:c1, #<Foo::ExpensiveObject: 1>, #<Foo::ExpensiveObject: 2>, [:c2, #<Foo::ExpensiveObject: 3>, #<Foo::ExpensiveObject: 4>, #<Foo::ExpensiveObject: 5>, [:c1, #<Foo::ExpensiveObject: 1>, #<Foo::ExpensiveObject: 2>, [:c2, #<Foo::ExpensiveObject: 3>, #<Foo::ExpensiveObject: 4>, #<Foo::ExpensiveObject: 5>, [:c1, #<Foo::ExpensiveObject: 1>, #<Foo::ExpensiveObject: 2>, []]]]]] $ cat eo.rb #!/usr/bin/ruby module ScratchArgument def scratch_method(name) meth = instance_method(name) define_method(name) do |*args0| *eo = *yield imeth = meth.bind(self) (class << self; self; end).class_eval do define_method(name) do |*args| args.unshift(*eo) imeth.call(*args) end end args0.unshift(*eo) imeth.call(*args0) end end end class Foo extend ScratchArgument class ExpensiveObject @@count = 0 def initialize @id = @@count += 1 p self end def inspect "#<#{self.class.name}: #{@id}>" end end def c1(tmp1, tmp2, i) if i <= 0 [] else [:c1, tmp1, tmp2, c2(i - 1)] end end scratch_method(:c1) do [ExpensiveObject.new, ExpensiveObject.new] end def c2(tmp1, tmp2, tmp3, i) if i <= 0 [] else [:c2, tmp1, tmp2, tmp3, c1(i - 1)] end end scratch_method(:c2) do [ExpensiveObject.new, ExpensiveObject.new, ExpensiveObject.new] end end result = Foo.new.c1(ARGV.empty? ? 3 : ARGV.first.to_i) require 'pp' pp result -- Nobu Nakada