Just two ideas, it's too late to actually think ;-)
you can change your 'ignored' vesion to something more acceptable:
...
def c1
@c1_tmp1 ||= ExpensiveObject.new
@c1_tmp2 ||= ExpensiveObject.new
tmp1, tmp2 = @c1_tmp1, @c2.tmp2
...
end
I was thinking of some kind of delegation, but it got too messy so I
abandoned it.
Another possibility is to implement a pool of objects directly into
ExpensiveObject or to create a layer above it.
i.e. something like (not tested, not thread-safe, etc.):
class ExtensiveObjectPool
class << self
def initialize
@idle, @busy = [], []
end
def with(how_many)
objs = allocate(how_many)
yield *objs
ensure
release(objs)
end
def allocate(num)
ret = []
while num > 0 and not @free.empty?
num -= 1
ret << @free.pop
@busy << ret.last
end
while num > 0
num -= 1
ret << ExpensiveObject.new
@busy << ret.last
end
ret
end
def release(objs)
@busy.delete(*objs)
@free += objs
end
end
class Foo
def c1
ExtensiveObjectPool.with(2) do |tmp1, tmp2|
result = tmp1 + tmp2 + c2
end
end
def c2
ExtensiveObjectPool.with(2) do |tmp1, tmp2|
result = tmp1 + tmp2
end
end
end