class Module

def memoize_method(*method_ids)

object the method is called on.
memoized results do NOT ONLY depend on the arguments, but ALSO on the
Automatically memoize calls of the the methods +method_ids+. The
def memoize_method(*method_ids)
  method_ids.extend(ExtractLastArgumentOptions)
  method_ids, opts = method_ids.extract_last_argument_options
  include CacheMethods
  method_ids.each do |method_id|
    method_id = method_id.to_s.to_sym
    memoize_apply_visibility method_id do
      orig_method = instance_method(method_id)
      __send__(:define_method, method_id) do |*args|
        mc = __memoize_cache__
        if mc.key?(method_id) and result = mc[method_id][args]
          result
        else
          (mc[method_id] ||= {})[args] = result = orig_method.bind(self).call(*args)
          $DEBUG and warn "#{self.class} cached method #{method_id}(#{args.inspect unless args.empty?}) = #{result.inspect} [#{__id__}]"
          opts[:freeze] and result.freeze
        end
        result
      end
    end
  end
  method_ids.size == 1 ? method_ids.first : method_ids
end