Skip to content

Instantly share code, notes, and snippets.

@searls
Created October 18, 2018 20:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save searls/89901c5433bf930c3c4d9834c466348b to your computer and use it in GitHub Desktop.
Save searls/89901c5433bf930c3c4d9834c466348b to your computer and use it in GitHub Desktop.
A class-wrapping memoization dingus
def MemoMe(superclass)
# Ripped mostly out of
# https://github.com/ruby/ruby/blob/trunk/lib/delegate.rb
klass = Class.new(superclass)
methods = superclass.instance_methods
methods -= [:to_s, :inspect, :=~, :!~, :===, :instance_variable_get, :instance_variable_set]
klass.define_method(:initialize, lambda do |*args|
@__memo_me_instance = superclass.new(*args)
end)
klass.module_eval do
methods.each do |method|
define_method(method, lambda do |*args, &block|
target = self.instance_variable_get("@__memo_me_instance")#.__getobj__
cache = target.instance_variable_get("@__memo_me_store") ||
target.instance_variable_set("@__memo_me_store", {})
cache[method] ||= {}
if memo = cache[method][[args, block]]
return memo
else
cache[method][[args, block]] = target.__send__(method, *args, &block)
end
end)
end
end
klass.define_singleton_method :public_instance_methods do |all=true|
super(all) - superclass.protected_instance_methods
end
klass.define_singleton_method :protected_instance_methods do |all=true|
super(all) | superclass.protected_instance_methods
end
return klass
end
# Demo:
class Calculator
def add(a, b)
puts "Ugh adding two numbers is so expensive"
a + b
end
end
CachingCalculator = MemoMe(Calculator)
calculator = CachingCalculator.new
puts calculator.add(1, 1)
puts calculator.add(2, 2)
puts <<~TEXT
No more printing! Just math!
---
TEXT
calculator.add(1, 1)
calculator.add(2, 2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment