Sha256: 0c8ba5785e4759a917976d3e506c3830ec9bbb50b2127f71d8d575c4b60cfc84

Contents?: true

Size: 1.84 KB

Versions: 1

Compression:

Stored size: 1.84 KB

Contents

module PatternMatching
  ##
  # Encapsulates pattern matching behaviors such as deep-matching of collection
  # types as well as wildcard values such as `Any`.
  class PatternMatch

    attr_reader   :pattern
    alias_method  :value, :pattern

    def initialize(*pattern)
      @pattern = pattern
    end

    ##
    # As both self.pattern and other are slurped, they are guaranteed to begin as
    # Arrays (i.e. they are enumerable). Thus all matches begin by checking a match
    # as if the values are enumerable.
    def ===(*other)
      match_enumerable(pattern, other)
    end


  private ######################################################################

    ##
    # Enumerable arguments with different lengths are not equal, at least as long as
    # wildcards such as Head and Tail remain un-implemented. This is used as a
    # fast-reject clause. Otherwise, iteration is used to decide
    #
    # TODO: There might be a better way of determining which objects are legitimately
    #       useful as matachable collections than simply descending from Enumerable or
    #       responding to #length, #zip and #reduce, as is implicit here.
    def match_enumerable(from_self, from_other)
      return false if from_self.length < from_other.length
      combined = from_self.zip(from_other)
      combined.reduce(true) do |acc, (self_item, other_item)|
        acc && match_item(self_item, other_item)
      end
    end

    ##
    # Handles matching for non-collection values, including the logic behind
    # the wildcard Any. In the case of a collection, defers instead to #match_enumerable.
    def match_item(from_self, from_other)
      if Any == from_other
        true
      elsif Enumerable === from_other && Enumerable === from_self
        match_enumerable(from_self, from_other)
      else
        from_other === from_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/pattern_match.rb