Mention AroundDecorator in README.txt.
[decorate.git] / lib / decorate / memoize.rb
blobe9e2a571b5f3c23e3d37b35910ba3fbb260e201e
1 require "decorate"
2 require "decorate/create_alias"
4 module Decorate::Memoize
5   
6   # A naive memoization decorator, using a plain Hash as cache.
7   #
8   # Example usage:
9   #
10   #   require "decorate/memoize"
11   #
12   #   Decorate::Memoize.memoize
13   #   def factorial(n)
14   #     n == 0 ? 1 : n * factorial(n - 1)
15   #   end
16   #   factorial(7) # => 5040
17   #
18   # Memoization takes the arguments as well as the instance itself
19   # into account. You can also extend a module/class with
20   # Decorate::Memoize to leave off the module prefix. Note that this
21   # decorator doesn't work for methods that take a block.
22   def memoize
23     Decorate.decorate { |klass, method_name|
24       wrapped_method_name = Decorate.create_alias(klass, method_name, :memoize)
25       # TODO: should use weak hash tables
26       cache = Hash.new { |hash, key| hash[key] = {} }
27       klass.send(:define_method, method_name) { |*args|
28         icache = cache[self]
29         if icache.has_key?(args)
30           icache[args]
31         else
32           icache[args] = send(wrapped_method_name, *args)
33         end
34       }
35     }
36   end
37   module_function :memoize
39 end