On Jan 27, 2006, at 11:04 PM, Alex Combas wrote:

> module Memoize
>    MEMOIZE_VERSION = "1.2.0"

Set a constant to the module version, so user code can check it as  
needed.

>
>    # Memoize the method +name+.  If +file+ is provided, then the  
> method results
>    # are stored on disk rather than in memory.  This consumes  
> virtually no
>    # memory and is persistant.
>    def memoize(name, file=nil)
>       meth = method(name)

Grab a reference to the original method.

>       if file
>          cache = Hash.new.update(Marshal.load(File.read(file)))  
> rescue {}
>       else
>          cache = {}
>       end

Load an existing cache file, if requested and one exists.  Otherwise,  
set the cache to an empty Hash.

>       if file
>          (class << self; self; end).class_eval do
>             define_method(name) do |*args|
>                unless cache.has_key?(args)
>                   cache[args] = meth.call(*args)
>                   File.open(file, "wb+"){|f| Marshal.dump(cache, f) }
>                end
>                cache[args]
>             end
>          end

This is the singleton class trick James Britt described.  It this  
version, the cache is checked for an entry with all the arguments it  
was just called with.  If it's not found, the original method is  
triggered to add that entry to the cache.  The file is also modified  
to contain the new entry.  Either way, the cache now has the needed  
entry, which is returned.

>       else
>          (class << self; self; end).class_eval do
>             define_method(name) do |*args|
>                if cache.has_key?(args)
>                   cache[args]
>                else
>                   cache[args] ||= meth.call(*args)
>                end
>             end
>          end
>       end

Exact same thing, minus the file dump.  In fact, that whole if/else/ 
end chunk of code could be simplified to:

          (class << self; self; end).class_eval do
             define_method(name) do |*args|
                unless cache.has_key?(args)
                   cache[args] = meth.call(*args)
                   File.open(file, "wb+"){|f| Marshal.dump(cache,  
f) } if file
                end
                cache[args]
             end
          end

>       cache

Return the cache we will use for user code to examine/modify, if  
desired.

>    end

Hope that helps.

James Edward Gray II