On 1/27/06, James Edward Gray II <james / grayproductions.net> wrote:
> You bet.  It's a single file.  Just download the source from
> RubyForge and move /lib/memoize.rb into your path.  It will work just
> fine.
>

Thanks James!
Wow, dont want to fanboy here, but wow.

$cat fib.rb
def fib(n)
  return n if n < 2
  fib(n-1) + fib(n-2)
end
puts fib(35)

$ time ruby fib.rb
9227465

real    0m41.121s
user    0m37.128s
sys     0m3.854s

$cat mem_fib.rb
require "memoize"
include Memoize
def fib(n)
  return n if n < 2
  fib(n-1) + fib(n-2)
end
memoize(:fib)
puts fib(35)

$ time ruby mem_fib.rb
9227465

real    0m0.011s
user    0m0.008s
sys     0m0.003s

Yikes! This is definitly something I'm going to need to learn to use, and use
as often as possible. So anywho, took a quick peek at memoize.rb and was
again just blown away but this time because the entire file was only 39 lines
of code including white space! How can this be?

Unfortuantely, there are no comments to be had, so I was wondering
if someone would be so kind as to reply with inserted comments in the code,
(yes I know ruby is supposed to be readable, but im new, ok? :-)
Just as a precaution so that I don't make any weird assumptions,
something I'm prone to do. This would be greatly appreciated.

Bored? Nothing to do on a Friday night?
Well here is some source. Comment away all you bored rubyists!

module Memoize
   MEMOIZE_VERSION = "1.2.0"

   # 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)

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

      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
      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
      cache
   end



--
Alex Combas
http://noodlejunkie.blogspot.com/