From 5738c25f3351444adb7af1074f53f0e519851f12 Mon Sep 17 00:00:00 2001 From: "Kevin J. Lynagh" Date: Mon, 13 Aug 2012 21:05:01 -0700 Subject: [PATCH] Map matching should always check for presence of key, even if wildcard matching This is a manually applied version of Jason Jackson's (jasonjckn@gmail.com) patch: http://dev.clojure.org/jira/browse/MATCH-52 with additional code added for CLJS support. --- src/main/clojure/clojure/core/match.clj | 24 ++++++-- src/test/clojure/clojure/core/match/test/core.clj | 68 ++++++++++++++++++++- 2 files changed, 84 insertions(+), 8 deletions(-) diff --git a/src/main/clojure/clojure/core/match.clj b/src/main/clojure/clojure/core/match.clj index bfdbd25..d2c06f5 100644 --- a/src/main/clojure/clojure/core/match.clj +++ b/src/main/clojure/clojure/core/match.clj @@ -128,12 +128,22 @@ (.valAt this k not-found))) (defn val-at* - ([m k] (val-at m k nil)) + ([m k] (let [val (val-at m k ::not-found)] + (if (= val ::not-found) + (throw backtrack) + val))) ([m k not-found] (val-at m k not-found))) (defn val-at-expr [& args] - (if *clojurescript* - `(get ~@args) + (if *clojurescript* ;;then we need to inline the correct behavior + (if (= 3 (count args)) + `(get ~@args) + (let [[m k] args] + `(let [val# (get ~m ~k ::not-found)] + (if (= val# ::not-found) + (throw 0) + val#)))) + ;;If not ClojureScript, defer to val-at* `(val-at* ~@args))) ;; ============================================================================= @@ -849,8 +859,10 @@ (defn ^WildcardPattern wildcard-pattern ([] (WildcardPattern. '_ nil)) ([sym] - {:pre [(symbol? sym)]} - (WildcardPattern. sym nil))) + {:pre [(symbol? sym)]} + (if (= sym '_) + (WildcardPattern. (gensym) nil) + (WildcardPattern. sym nil)))) (defn wildcard-pattern? [x] (instance? WildcardPattern x)) @@ -1760,4 +1772,4 @@ (let [bindvars# (take-nth 2 bindings)] `(let ~bindings (match [~@bindvars#] - ~@body)))) \ No newline at end of file + ~@body)))) diff --git a/src/test/clojure/clojure/core/match/test/core.clj b/src/test/clojure/clojure/core/match/test/core.clj index 65f6165..e5f448a 100644 --- a/src/test/clojure/clojure/core/match/test/core.clj +++ b/src/test/clojure/clojure/core/match/test/core.clj @@ -76,11 +76,75 @@ (is (= (let [x {:a 1 :b 1}] (match [x] [{:a _ :b 2}] :a0 - [{:a 1 :c _}] :a1 + [{:a 1 :b 1}] :a1 [{:c 3 :d _ :e 4}] :a2 :else [])) :a1))) +(deftest map-pattern-match-2 + (is (= (let [x {:a 1 :b 1}] + (match [x] + [{:a _ :b 1}] :a0 + [{:a 1 :b _}] :a1 + [{:c 3 :d _ :e 4}] :a2 + :else [])) + :a0))) + +(deftest map-pattern-match-3 + (is (= (let [x {:a 1 :b 1 :c 1}] + (match [x] + [{:a _ :b 2}] :a0 + [{:a 1 :b _}] :a1 + [{:c 3 :d _ :e 4}] :a2 + :else [])) + :a1))) + +(deftest map-pattern-match-4 + (is (= (let [x {:a 1 :b 1}] + (match [x] + [{:a _ :b 2}] :a0 + [{:a _ :b _}] :a1 + [{:c 3 :d _ :e 4}] :a2 + :else [])) + :a1))) + +(deftest map-pattern-match-5 + (is (= (let [x {:a 1}] + (match [x] + [{:a 1 :b 1}] :a0 + [{:a _ :b _}] :a1 + [{:c 3 :d _ :e 4}] :a2 + :else [])) + []))) + +(deftest map-pattern-match-6 + (is (= (let [x {:a 1 :b 1}] + (match [x] + [{:b 1}] :a0 + [{:a _ :b _}] :a1 + [{:a _ :b _}] :a2 + :else [])) + :a0))) + +(deftest map-pattern-match-7 + (is (= (let [x {:a 1 :b 1}] + (match [x] + [{}] :a0 + [{:a _ :b _}] :a1 + [{:a 1 :b 1}] :a2 + :else [])) + :a0))) + +(deftest map-pattern-match-8 + (is (= (let [x {:a 1 :b 1}] + (match [x] + [{:x nil :y nil}] :a0 + [{:a _ :b _}] :a1 + [{:a 1 :b 1}] :a2 + :else [])) + :a1))) + + (deftest map-pattern-match-only-1 (is (= (let [x {:a 1 :b 2}] (match [x] @@ -650,4 +714,4 @@ [:b b] :a1 [:c] :a2 :else :a3)) - :a2))) \ No newline at end of file + :a2))) -- 1.7.8