Reputation: 358
I have Memoize module, that provides methods for caching of class and instance methods.
module Memoize
def instance_memoize(*methods)
memoizer = Module.new do
methods.each do |method|
define_method method do
@_memoized_results ||= {}
if @_memoized_results.include? method
@_memoized_results[method]
else
@_memoized_results[method] = super()
end
end
end
end
prepend memoizer
end
def class_memoize(*methods)
methods.each do |method|
define_singleton_method method do
@_memoized_results ||= {}
if @_memoized_results.include? method
@_memoized_results[method]
else
@_memoized_results[method] = super()
end
end
end
end
end
This is an example of how I use it:
class Foo
extend Memoize
instance_memoize :instance_method1, :instance_method2
class_memoize :class_method1, :class_method2
...
end
Please advice how to avoid code duplication in this module.
Upvotes: 1
Views: 70
Reputation: 121000
One might define a lambda:
λ = lambda do
@_memoized_results ||= {}
if @_memoized_results.include? method
@_memoized_results[method]
else
@_memoized_results[method] = super()
end
end
And. then:
define_method method, &λ
Please be aware of an ampersand in front of λ
, it is used to notice define_method
about it’s receiving a block, rather than a regular argument.
I did not get what failed with this approach on your side, but here is a bullet-proof version:
method_declaration = %Q{
def %{method}
@_memoized_results ||= {}
if @_memoized_results.include? :%{method}
@_memoized_results[:%{method}]
else
@_memoized_results[:%{method}] = super()
end
end
}
methods.each do |method|
class_eval method_declaration % {method: method}
end
Upvotes: 1