Hello
I have a class Foo which has a number of heavy, CPU intensive, number
crunching methods that take parameters.
class Foo
attr_reader :x, :y, ...
def calc1(a,b,c)
...# complicated, time-consuming calculation...
end
def calc2(a,b)
...# complicated, time-consuming calculation...
end
...
end
Foo is immutable. If a client calls a method more than once using the
same set of parameters, the same result will be calculated and
returned.
To avoid the work of recalculating a result if a client calls a method
more than once with the same set of parameters, I revised Foo to cache
results in a hash for each method for each set of parameters. The
keys in the hashes are arrays of parameters.
class Foo
def calc1(a,b,c)
param_array = [a,b,c]
@cache_calc1 ||= {}
return @cache_calc1[param_array] if @cache_calc1[param_array]
ans = ... #same complicated, time-consuming calculation...
@cache_calc1[param_array] = ans
end
def calc2(a,b)
param_array = [a,b]
@cache_calc2 ||= {}
return @cache_calc2[param_array] if @cache_calc2[param_array]
ans = ... #same complicated, time-consuming calculation...
@cache_calc2[param_array] = ans
end
end
This works great -- calculations for a given set of parameters on
each method are now done only once. However, the code seems rote,
repetitive and intrusive to the original methods.
Is there a way to do this in Ruby in a more declarative, more DRY way?
I am envisioning it should be possible to add a simple, single line to
the original Foo, a la
class Foo
cache_calculation :calc1, :calc2
#rest of Foo unchanged
end
My newbie ruby skills are not up to task writing such a
cache_calculation method on Class, to wrap and call the original
method and provide the caching, but it seems it should be simple to
do.
class Class
def cache_calculation(syms)
syms.each do |sym|
???
end
end
end
Can anyone provide the necessary snippet or otherwise advise or point
me to a solution to this?
Thanks!
Brian