Sha256: 86dda5ab850b6b06e46ba465602a29d8b1a9c1cf5192685395ccd739135d3c3d

Contents?: true

Size: 1.51 KB

Versions: 1

Compression:

Stored size: 1.51 KB

Contents

# Copyright John Anderson 2015-2016

require_relative 'memoed_methods'

module Lemo
  module Memo
    include MemoedMethods

    module ClassMethods
      def memoed_methods
        @memoed_methods ||= {}
      end

      # provide a legal ivar name from a method name. instance variables
      # can't have ? ! and other punctuation. Which isn't handled. Obviously.
      def ivar_from( maybe_meth )
        :"@_memo_#{maybe_meth.to_s.tr ILLEGAL_IVAR_CHARS,'pi'}"
      end

      def lemo( meth )
        unbound_previous_method = instance_method meth

        # still doesn't prevent memoisation of methods with an implicit block
        unless unbound_previous_method.parameters.empty?
          raise ArgumentError, "can't memo #{meth} with parameters"
        end

        memoed_methods[meth] = unbound_previous_method
        ivar = ivar_from meth

        define_method meth do
          # This gets executed on every call to meth, so make it fast.
          if instance_variable_defined? ivar
            instance_variable_get ivar
          else
            # bind the saved method to this instance, call the result ...
            to_memo = unbound_previous_method.bind( self ).call
            # ... memo it and return value
            instance_variable_set ivar, to_memo
          end
        end

        meth
      end

      # for all the things using memo already
      alias memo lemo
    end

    # hook in class methods on include
    def self.included( other_module )
      other_module.extend ClassMethods
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
lemo-0.1.0 lib/lemo/memo.rb