Sha256: fbd8cb9440c95aac36682bdd4b790a26f61580469e3580683465ad834a4a1c73

Contents?: true

Size: 1.85 KB

Versions: 1

Compression:

Stored size: 1.85 KB

Contents

# Copyright John Anderson 2015-2016

require_relative 'memoed_methods'

module Lemo
  # simple replacement for ||= (y'know or-or-equals)
  # in others words stores values as plain old @name, and nil means same as does-not-exist
  module Ormo
    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.
      # WARNING meth, meth? and meth! will access the same ivar.
      def ivar_from( meth )
        :"@#{meth.to_s.delete ILLEGAL_IVAR_CHARS}"
      end

      # WARNING race condition if two threads concurrently define the same
      # memo'ed method on the same class. Unlikely, but still.
      def ormo( 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

        # keep this for initial calculation, and recalculation
        memoed_methods[meth] = unbound_previous_method
        ivar = ivar_from meth

        # Define the class using instance variable @ syntax, for fastest
        # runtime. Use class_eval to define an instance method, cos self is the
        # class (or singleton class) right now
        class_eval <<-RUBY, __FILE__, __LINE__
          def #{meth}
            #{ivar} ||= _memoed_methods[:#{meth}].bind(self).call
          end
        RUBY

        # allow chaining of symbol returned from def
        meth
      end

      # for all the things using memo already
      alias memo ormo
    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/ormo.rb