#--
# Credit goes to Robert Feldt.
#++

class Module

  # Directive for making your functions faster by trading
  # space for time. When you "memoize" a method/function
  # its results are cached so that later calls with the
  # same arguments returns results in the cache instead
  # of recalculating them.
  #
  #   class T
  #     def initialize(a)
  #       @a = a
  #     end
  #     def a
  #       "#{@a ^ 3 + 4}"
  #     end
  #     memoize :a
  #   end
  #
  #   t = T.new
  #   t.a.__id__ == t.a.__id__  #=> true
  #
  def memoize(*meths)
    @_MEMOIZE_CACHE ||= Hash.new
    meths.each do |meth|
      mc = @_MEMOIZE_CACHE[meth] = Hash.new
      old = instance_method(meth)
      new = proc do |*args|
        if mc.has_key? args
          mc[args]
        else
          mc[args] = old.bind(self).call(*args)
        end
      end
      send(:define_method, meth, &new)
    end
  end

end

# This allows memoize to work in main and instance scope too.
#--
# Would this be good to have? Will need to modify for instance level, if so.
#++

def memoize(*args)
  Object.memoize(*args)
end


#  _____         _
# |_   _|__  ___| |_
#   | |/ _ \/ __| __|
#   | |  __/\__ \ |_
#   |_|\___||___/\__|
#
=begin test

  require 'test/unit'

  class T
    def initialize(a)
      @a = a
    end
    def a
      "#{@a ^ 3 + 4}"
    end
    memoize :a
  end

  # test

  class TC_Memoize < Test::Unit::TestCase

    def setup
      @t = T.new(2)
    end

    def test_memoize_01
      assert_equal( @t.a, @t.a )
    end

    def test_memoize_02
      assert_equal( @t.a.__id__, @t.a.__id__ )
    end

    def test_memoize_03
      assert_equal( @t.a.__id__, @t.a.__id__ )
    end

  end

=end
