Module Memoizable
In: lib/facets/supplemental/facets/memoizable.rb

Memoization is an optimization technique used primarily to speed up programs by having function calls avoid repeating the calculation of results for previously-processed inputs.

When you "memoize" a method/function using Memoizable its results are cached so that later calls return results from the cache instead of recalculating them.

  class T
    include Memoizable

    def initialize(a)
      @a = a
    end

    def a
      "#{@a ^ 3 + 4}"
    end

    memoize :a
  end

  t = T.new(10)
  (t.a.__id__ == t.a.__id__)  #=> true

This method can also be used at the instance level to cache singleton (qua class) methods by including it in the singleton class.

Methods

Classes and Modules

Module Memoizable::Copy

Public Class methods

[Source]

# File lib/facets/supplemental/facets/memoizable.rb, line 44
  def self.append_features(base)
    Module == base ? super(base) : base.extend(self)
  end

[Source]

# File lib/facets/supplemental/facets/memoizable.rb, line 39
  def self.cache
    @cache
  end

Public Instance methods

Directive for making your functions faster by trading space for time. When you "memoize" a method/function using memoize its results are cached so that later calls with the same arguments return results from the cache instead of recalculating them.

The memoize method also handles a few options to alter behavior of the memoization:

  :class     => true      cache per-class not per-object
  :freeze    => true      freeze the memoized return values
  :arguments => false     do not index cache by arguments

[Source]

# File lib/facets/supplemental/facets/memoizable.rb, line 60
  def memoize(*method_names)
    options = Hash === method_names.last ? method_names.pop : {}

    options[:arguments] = true if options[:arguments].nil?  # default to true

    ref = options[:class]     ? 'self.class.name'       : 'self'
    frz = options[:freeze]    ? '.freeze'               : ''
    arg = options[:arguments] ? '[__a__, block_given?]' : 'nil'

    code = ""
    method_names.each do |m|
      code << "alias_method '\#{ m }:memo', '\#{ m }'\nprivate '\#{ m }:memo'\ndef \#{ m }(*__a__,&__b__)\nc = Memoizable.cache[\#{ref}][:'\#{ m }']\nk = \#{arg}\nif c.has_key?(k)\nc[k]\nelse\nc[k] = __send__('\#{ m }:memo',*__a__,&__b__)\#{frz}\nend\nend\n"
    end
    module_eval(code)
  end

Remove the memoized value from the memoization cache. The next time a memoized methos is called if will be remomoized.

[Source]

# File lib/facets/supplemental/facets/memoizable.rb, line 92
  def rememoize(*method_names)
    if Memoizable.cache[self]
      if method_names.empty?
        Memoizable.cache.delete(self)
      else
        method_names.each do |m|
          Memoizable.cache[self].delete(m.to_sym)
        end
      end
    end
    if Memoizable.cache[self.class.name]
      if method_names.empty?
        Memoizable.cache.delete(self.class.name)
      else
        method_names.each do |m|
          Memoizable.cache[self.class.name].delete(m.to_sym)
        end
      end
    end
  end

[Source]

# File lib/facets/supplemental/facets/memoizable.rb, line 114
  def unmemoize(*method_names)
    rememoize(*method_names)
    method_names.each do |m|
      alias_method name, "#{ m }:memo"
    end
  end

[Validate]