From 0ca6b42275723f223142e6fc3191ccb888bfe580 Mon Sep 17 00:00:00 2001
From: Chris Gray <chrismgray@gmail.com>
Date: Thu, 12 Jan 2012 22:22:50 -0700
Subject: [PATCH 2/2] Use the new multimethod and add some tests.

---
 src/main/clojure/clojure/core/match.clj           |   20 +++++++---
 src/test/clojure/clojure/core/match/test/core.clj |   42 ++++++++++++++++++---
 2 files changed, 50 insertions(+), 12 deletions(-)

diff --git a/src/main/clojure/clojure/core/match.clj b/src/main/clojure/clojure/core/match.clj
index c7dfdec..fdb7657 100644
--- a/src/main/clojure/clojure/core/match.clj
+++ b/src/main/clojure/clojure/core/match.clj
@@ -555,12 +555,19 @@
   (letfn [(pseudo-patterns [matrix i]
             (->> (column matrix i)
               (filter pseudo-pattern?)))
-          
+
+          (matrix-splitter [rows]
+            (let [f (first rows)
+                  [x y] (split-with #(if (mutually-exclusive-inequality? f)
+                                       (mutually-exclusive-inequality? %)
+                                       (pattern-equals f %)) (rest rows))]
+              [(cons f x) y]))
+
           (default-matrix  [matrix]
-            (let [m (pattern-matrix
+            (let [rs (rows matrix)
+                  m (pattern-matrix
                      (into []
-                       (drop-while #(not (wildcard-pattern? (first %)))
-                                   (rows matrix)))
+                           (drop (count (first (matrix-splitter (map first rs)))) rs))
                      (occurrences matrix))]
               (if-not (empty-matrix? m)
                 (do
@@ -577,7 +584,8 @@
           ;; column. everything including and after a wildcard pattern is always
           ;; the default matrix
           (group-rows [rows]
-            (let [[l r] (split-with #(not (wildcard-pattern? (first %))) rows)]
+            (let [[s-m-1 s-m-2] (map count (matrix-splitter (map first rows)))
+                  [l r] [(take s-m-1 rows) (drop s-m-1 rows)]]
               (letfn [(group [[r & rs :as rows]]
                         (if (seq rows)
                           (let [[fd rd] ((juxt filter remove)
@@ -609,7 +617,7 @@
           ;; Returns a vector of relevant constructors in column i of matrix
           (column-constructors [matrix i]
             (let [cs (group-vector-patterns (column matrix i))]
-              (collapse (take-while (comp not wildcard-pattern?) cs))))
+              (collapse (first (matrix-splitter cs)))))
 
           ;; Compile a decision trees for each constructor cs and returns a clause list
           ;; usable by a switch node
diff --git a/src/test/clojure/clojure/core/match/test/core.clj b/src/test/clojure/clojure/core/match/test/core.clj
index 2d7dd03..8691e1d 100644
--- a/src/test/clojure/clojure/core/match/test/core.clj
+++ b/src/test/clojure/clojure/core/match/test/core.clj
@@ -82,20 +82,20 @@
          :a1)))
 
 (deftest map-pattern-match-only-1
-  (is (and (= (let [x {:a 1 :b 2}]
-                (match [x]
+  (is (= (let [x {:a 1 :b 2}]
+           (match [x]
                   [({:a _ :b 2} :only [:a :b])] :a0
                   [{:a 1 :c _}] :a1
                   [{:c 3 :d _ :e 4}] :a2
                   :else []))
-              :a0)
-           (= (let [x {:a 1 :b 2 :c 3}]
-                (match [x]
+           :a0))
+  (is (= (let [x {:a 1 :b 2 :c 3}]
+           (match [x]
                   [({:a _ :b 2} :only [:a :b])] :a0
                   [{:a 1 :c _}] :a1
                   [{:c 3 :d _ :e 4}] :a2
                   :else []))
-              :a1))))
+         :a1)))
 
 (deftest map-pattern-match-bind-1
   (is (= (let [x {:a 1 :b 2}]
@@ -195,6 +195,36 @@
                 :else :a4)
          :a2)))
 
+(deftest guard-pattern-match-5
+  (is (=
+       (let [oddp odd?]
+         (match [1 2]
+                [a :when odd? b :when odd?] :a1
+                [a :when oddp _] :a2
+                [_ b :when even?] :a3
+                :else :a4))
+       :a2)))
+
+(deftest unequal-equal-tests
+  (is (=
+       (match ["foo" "bar"]
+              [#".*" #"baz"] :a1
+              [#"foo" _] :a2
+              [_ "bar"] :a3
+              :else :a4)
+       :a2)))
+
+(deftest unequal-equal-tests-2
+  (is (=
+       (let [a 1 b 1]
+         (match [1 2]
+                [a 3] :a1
+                [1 2] :a2
+                [2 _] :a5
+                [_ 3] :a4
+                :else :a3))
+       :a2)))
+
 ;; use ':when pattern to match literal :when (as opposed to guard syntax)
 (deftest literal-when-match-1
   (is (= (let [x :as y :when z 1]
-- 
1.7.7.3

