Search code examples
rubymemoization

How to memoize all instances of a class without repeated code?


I'm using Memoist and I have a specific case where all the methods of my class need to be memoized. I would like to be able to memoize them without the need to write the memoize :instance_method_name for each method. I would like to do something like:

class MyClass
  extend Memoist

  def initialize
    instance_methods(false).each(&:memoize)
  end

  private

  def method1
  end

  def method2
  end

  def method3
  end
end

But of course it does not work because instance_methods is not valid.


Solution

  • You just need to call the methods on the correct object:

    class MyClass
      extend Memoist
    
      private
    
      def method1
      end
    
      def method2
      end
    
      def method3
      end
    
      instance_methods(false).each(&method(:memoize))
    end
    

    Module#instance_methods is an instance method of the Module class, not an instance method of the MyClass class. Therefore, you need to call it on an instance of Module, not on an instance of MyClass.

    Likewise, you are calling Memoist#memoize on an instance of Symbol, but you need to call it on an instance of Memoist instead, i.e. in this case on MyClass.

    Note that even if the code you wrote did work, it wouldn't do what you think it does. memoize works by replacing the method with a new method that wraps and caches the old method. However, if your code worked the way you wanted it to, every time you create a new object, it would have called memoize again, and thus wrapped the already wrapped method, and then wrapped the wrapper of the already wrapped method, and then wrapped the wrapper of the wrapper of the already wrapped method, and so on.