Sha256: dac99ea36e224ba1ef381a20fd37ac61a96486b1b72addc52a5a45dcd855c0ca

Contents?: true

Size: 1.69 KB

Versions: 1

Compression:

Stored size: 1.69 KB

Contents

module PatternMatching
  ##
  # Taken nearly verbatim from the idea presented by Avdi Grimm in an episode of
  # the fantastic Ruby Tapas series, including the use of the >> (right-shift) operator
  # as a "guard" operator, as visually stands out compared to other define-able
  # binary operators but it lacks idiomatic re-use the way that << (left-shift) does.
  # It also feels a little bit like the \\ guards used in Elixir, which I would have
  # used, if I could find a way to have Ruby treat either \\ or // as a binary operator.
  class Bindings < BasicObject

    def initialize
      @bindings = ::Hash.new do |hash, key|
        ::PatternMatching::Bindings::BoundValue.new(hash, key)
      end
    end

    ##
    # Hello darkness, my old friend.
    def method_missing(msg, *)
      @bindings[msg]
    end


    ##
    # The interesting work of Bindings happens in this class.
    #
    # Allows setting up guards via the >> oprator.
    #
    # If guards pass, or no guards have been added to a BoundValue,
    # then comparing via == or === with that BoundValue will always
    # return true, and will save the compared-to value in the hash,
    # presumably provided by an instance of the Bindings class.
    class BoundValue
      def initialize(bindings, name)
        @bindings = bindings
        @name     = name
        @guards   = []
      end

      def ==(other)
        return false unless @guards.all? { |g| g === other }
        @bindings[@name] = other
        true
      end

      def ===(other)
        return false unless @guards.all? { |g| g === other }
        @bindings[@name] = other
        true
      end

      def >>(guard)
        @guards << guard
        self
      end
    end

  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
pattern_matching-0.1.0 lib/pattern_matching/bindings.rb