Victor "Zverok" Shepelev wrote: > Hi all. > > I have some huge class with aspects of functionality spreaded in several > source files. > > And in some of those aspects there is the same picture: > --- > class MyClass > def push_something(obj) > @something_list ||= [] > @something_list << obj > end > > def use_something(i) > (@something_list ||= [])[i] > end > end > --- > > Then I note (through profiler) various push_XXX spend too much time in > checking is @XXX_list initialized. Then I change it: > > --- > class MyClass > alias :initialize_without_something :initialize > > def initialize(*arg) > initialize_without_something(*arg) > @something_list = [] > end > > def push_something(obj) > @something_list << obj > end > > def use_something(i) > @something_list[i] > end > end > --- > > Now push_XXX and use_XXX work cleaner and faster, but all those initialize > aliases (now I have 5 or 6) don't seem to be very elegant. > > Is there better solution? > > (to be clear, all those push_XXX are NOT similar - some of them push object > to hashes, others to arrays, params count differ and so on - so, they can't > be generated at once through metaprogramming) > > Thanks. > > V. > I don't know how this will profile--it has the disadvantage of generating more singletons than you might want, and there is the extra overhead of an attr_reader rather than just @something_list. class MyClass def method_missing(m,*) if m == :something_list @something_list = [] class << self attr_reader :something_list end something_list else super end end def push_something(obj) something_list << obj end def use_something(i) something_list[i] end end mc = MyClass.new mc.push_something 3 p mc # ==> #<MyClass:0xb7d02114 @something_list=[3]> Also, the method_missing def would need to know about each such attr, which seems to contradict your goal of distributing that information to lots of files. A little metaprogramming would help with that, since with this approach you only need to metaprogram the accessors, and not all the push_, pop_ etc. methods. Define a class method that registers things like "something_list", and the method_missing can lookup in the registered methods. If you can tolerate a register method as well as the accessor overhead, then this gives me another idea, which doesn't generate singletons: class MyClass @reg_methods_defined = false @reg = {} class << self attr_reader :reg def define_reg_methods unless @reg_methods_defined @reg.each do |m,| attr_reader m end @reg_methods_defined = true end end end def initialize self.class.define_reg_methods self.class.reg.each do |m, (iv, bl)| instance_variable_set(iv, bl.call) end end def self.register m, &bl @reg[m] = ["@#{m}", bl] end end class MyClass register :something_list do [] end def push_something(obj) something_list << obj end def use_something(i) something_list[i] end end mc = MyClass.new mc.push_something 3 p mc # ==> #<MyClass:0xb7d65a7c @something_list=[3]> Getting this to work for subclasses as well is left as an exercise to the reader ;) -- vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407