Cheap Ruby memoize using Hash default block
As MenTaLguY mentioned, you can give a block to Hash.new in Ruby. This leads to pretty simple memoization. E.g.,
# Demonstrate a "memoizing" behavior of certain Hash usage
def fib_n ( n )
if n <= 1
n
else
fib_n( n-1 ) + fib_n( n-2 )
end
end
$fib_mh = Hash.new do |h,n|
if n <= 1
h[n] = n
else
h[n] = fib_m( n-1 ) + fib_m( n-2 )
end
end
def fib_m ( n )
$fib_mh[ n ]
end
def compar (lim)
# puts lim
strt = Time.now
puts fib_n(lim)
mid = Time.now
puts fib_m(lim)
last= Time.now
puts "Lim(#{lim}), no memoing, takes #{mid-strt} seconds."
puts "Lim(#{lim}), memoing, takes #{last-mid} seconds."
end
compar( ARGV[0].to_i )
Unless you have a lot of time, don't try running this with an argument bigger than the mid-30s.
The RAA has a memoize mixin, but it doesn't use quite the same trick. It's still pretty short, though. The guts:
module Memoize
MEMOIZE_VERSION = "1.1.0"
def memoize(name)
meth = method(name)
cache = {}
(class << self; self; end).class_eval do
define_method(name) do |*args|
cache.has_key?(args) ? cache[args] : cache[args] ||= meth.call(*args)
end
end
cache
end
end
11:56:34 PM