From: beng Date: 2005-12-09T04:07:35+09:00 Subject: Transparent Caching Idiom I've made good use of this idiom recently, and wanted to share it. Once this code is active, any method named with a "_c" suffix is automatically cached. The method is assumed to follow a simple contract: It performs no side-effects / mutations, and it's arguments properly implement "Object.hash". This is specifically useful for expensive but functional calculations. Enjoy! --Ben (b@gimpert.com) # class Class alias old_new new def new(*args, &block) Class.defc_wrap(old_new(*args, &block)) end def Class.defc_wrap(obj) klass = obj.class defc_methods = obj.methods.select { |n| n =~ /_c$/ } defc_methods.each do |name| meth = obj.method(name) wrapped_name = Class.defc_next_name(klass) cache = klass.class_eval("@#{wrapped_name} = {}") wrapper = Proc.new do |*args_a| arg_hash = args_a.hash if cache.has_key?(arg_hash) cache[arg_hash] else cache[arg_hash] = meth.call(*args_a) end end klass.send(:alias_method, wrapped_name, name) klass.send(:define_method, name, wrapper) end obj end def Class.defc_next_name(obj) klass = obj.class i = 1 i += 1 while obj.respond_to?("_defc_#{i}") || obj.instance_variables.member?("@_defc_#{i}") "_defc_#{i}" end end