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 ![:wink: :wink:](https://emoji.discourse-cdn.com/twitter/wink.png?v=12)
···
--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407