[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Simple memoization module

Marcin Raczkowski

6/16/2008 11:25:00 AM

If you ewer wanted to easilly cache memoizable functions (ones that
output depend ONLY on parameters given)- here's a way!

Implementation contains sweeping support for classes/modules and methods
inside those classes, ActiveRecord logger is used by memcache-client
library so I provide it becouse i'm to lazy to remove that dependency in
3rd party pugin.

If anyone shows interest i'll pack it as gem, and mayby add some stuff,
all requests are welcome

Marcin Raczkowski
www.softwarelab.eu

=========================================================================

module Memoization
# store keys for sweeping
def Memoization.add_key(key)
@keys ||= []
@keys |= [key]
end

# remove keys that belongs to given class/method
def Memoization.sweep(klass, method=nil)
reg = method ? Regexp.new("^#{klass}:#{method}") :
Regexp.new("^#{klass.to_s}")
@keys.select{|k| reg.match(k) }.each{|k| Cache.delete(k)}
end

# sugar that allows SomeClass.sweep
def sweep(method = nil)
Memoization.sweep(self, method)
end

# example usage in test case, takes names of methods to memoize
def memoize(*names)
return unless defined?(Cache)

names.each do |name|
name = name.to_s
new_name = "nc_"+name
alias_method(new_name, name)
define_method(name) do |*args|
key = "#{self.class.name}:#{name}(#{args.hash})"
Memoization.add_key(key)
Cache.get(key, 60) {
self.send(new_name.to_sym, *args)
}
end
end

end
end

# doing inclusion into module / class
class Class
include Memoization
end

class Module
include Memoization
end

# workaround for non-rails environment
unless defined?(ActiveRecord::Base)
module ActiveRecord; end
class ActiveRecord::Base;
def self.logger; Logger.new(STDOUT); end;
end
end

if __FILE__ == $0
# testcase require memcached server running on default port

require 'test/unit'
require 'rubygems'
require 'memcache'
CACHE = MemCache.new 'localhost:11211', :namespace => 'moization'
require 'memcache_util'
require 'logger'

class A
def normal(a); a; end
def random(); rand; end
memoize :normal, :random
end

class TC_MyTest < Test::Unit::TestCase
def test_behaviour
assert(A.new.normal(:a) == A.new.normal(:a))
assert(A.new.normal(:a) != A.new.normal(:b))
rnd = A.new.random
assert(A.new.random == A.new.random)
A.sweep
assert(A.new.random != rnd)
assert(A.new.random == A.new.random)
rnd = A.new.random
A.sweep(:random)
assert(A.new.random != rnd)
assert(A.new.random == A.new.random)
end
end
end