problem:
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.
Solution:
> original I think) on RAA (http://raa.ruby-lang.org/project/memoize).
to do. A handful of lines. I can see it works.
#my test code
f = Foo.new
f.memoize(:calc1)
f.memoize(:calc2)
f.calc1(1,2,3)
f.calc1(1,2,3) #yep its working
f.calc1(7,8,9) #yep its working
If I can ask a Ruby 101 question about it... Isn't "cache" in the
module (pasted below in its entirety it is so short) only a local
variable? Why does is retain state? How can one, for example, access
the cache to see the state of the cache?
Thanks!
--Brian
MEMOIZE_VERSION = "1.0.0"
def memoize(name)
meth = method(name)
cache = {}
(class << self; self; end).class_eval do
define_method(name) do |*args|
cache[args] ||= meth.call(*args)
end
end
end
end
Delicious.
No comments:
Post a Comment