def memoize(*method_names)
identifier = method_names.pop[:identifier] if method_names.last.is_a?(Hash)
method_names.each do |method_name|
unmemoized_method = Memoist.unmemoized_method_for(method_name, identifier)
memoized_ivar = Memoist.memoized_ivar_for(method_name, identifier)
Memoist.memoist_eval(self) do
include InstanceMethods
if method_defined?(unmemoized_method)
warn "Already memoized #{method_name}"
return
end
alias_method unmemoized_method, method_name
mm = MemoizedMethod.new(method_name, memoized_ivar, instance_method(method_name).arity)
memoized_methods << mm
if mm.arity == 0
module_eval "def \#{method_name}(reload = false)\nskip_cache = reload || !instance_variable_defined?(\"\#{memoized_ivar}\")\nset_cache = skip_cache && !frozen?\n\nif skip_cache\nvalue = \#{unmemoized_method}\nelse\nvalue = \#{memoized_ivar}\nend\n\nif set_cache\n\#{memoized_ivar} = value\nend\n\nvalue\nend\n", __FILE__, __LINE__ + 1
else
module_eval "def \#{method_name}(*args)\nreload = Memoist.extract_reload!(method(\#{unmemoized_method.inspect}), args)\n\nskip_cache = reload || !(instance_variable_defined?(\#{memoized_ivar.inspect}) && \#{memoized_ivar} && \#{memoized_ivar}.has_key?(args))\nset_cache = skip_cache && !frozen?\n\nif skip_cache\nvalue = \#{unmemoized_method}(*args)\nelse\nvalue = \#{memoized_ivar}[args]\nend\n\nif set_cache\n\#{memoized_ivar} ||= {}\n\#{memoized_ivar}[args] = value\nend\n\nvalue\nend\n", __FILE__, __LINE__ + 1
end
if private_method_defined?(unmemoized_method)
private method_name
elsif protected_method_defined?(unmemoized_method)
protected method_name
end
end
end
method_names.length == 1 ? method_names.first : method_names
end