From b3c707092ea6bc0e3220c95a96eab84f724b71fd Mon Sep 17 00:00:00 2001 From: Beau Fabry Date: Tue, 19 Apr 2016 15:15:06 -0700 Subject: [PATCH 1/2] add a submap path --- src/clj/com/rpl/specter.cljx | 19 +++++++++++++++++++ test/com/rpl/specter/core_test.cljx | 12 ++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/clj/com/rpl/specter.cljx b/src/clj/com/rpl/specter.cljx index c0802bf..690930d 100644 --- a/src/clj/com/rpl/specter.cljx +++ b/src/clj/com/rpl/specter.cljx @@ -217,6 +217,25 @@ (set/union newset)) ))) +(defpath + submap* + [m-keys] + (select* [this structure next-fn] + (next-fn (merge (zipmap m-keys (repeat nil)) (select-keys structure m-keys)))) + + (transform* [this structure next-fn] + (let [submap (merge (zipmap m-keys (repeat nil)) (select-keys structure m-keys)) + newmap (next-fn submap)] + (merge (apply dissoc structure m-keys) + newmap)))) + +(defn submap + "Navigates to the specified submap (by attempting a get for each key). + In a transform, that submap in the original map is changed to the new + value of the submap." + [& m-keys] + (submap* m-keys)) + (defpath walker [afn] diff --git a/test/com/rpl/specter/core_test.cljx b/test/com/rpl/specter/core_test.cljx index d23bd34..145db2f 100644 --- a/test/com/rpl/specter/core_test.cljx +++ b/test/com/rpl/specter/core_test.cljx @@ -573,6 +573,18 @@ (= (s/setval (s/subset s3) s4 combined) (-> combined (set/difference s2) (set/union s4))) )))) +(deftest submap-test + (is (= [{:foo 1, :baz nil}] + (s/select [(s/submap :foo :baz)] {:foo 1 :bar 2}))) + (is (= {:foo 1, :barry 1} + (s/setval [(s/submap :bar)] {:barry 1} {:foo 1 :bar 2}))) + (is (= {:bar 1, :foo 2, :baz nil} + (s/transform [(s/submap :foo :baz) s/ALL s/LAST (comp not nil?)] inc {:foo 1 :bar 1}))) + (is (= {:a {:new 1} + :c {:new 1 + :old 1}} + (s/setval [s/ALL s/LAST (s/submap)] {:new 1} {:a nil, :c {:old 1}})))) + (deftest nil->val-test (is (= {:a #{:b}} (s/setval [:a s/NIL->SET (s/subset #{})] #{:b} nil))) From eb20e86f9cfb108d7482a2fef72ef62f82f40d20 Mon Sep 17 00:00:00 2001 From: Beau Fabry Date: Tue, 19 Apr 2016 17:24:00 -0700 Subject: [PATCH 2/2] Address PR comments * Behave the same as select-keys for non-existent keys * Remove variadic input redirection * Use reduce to remove data instead of apply --- src/clj/com/rpl/specter.cljx | 18 +++++++----------- test/com/rpl/specter/core_test.cljx | 12 ++++++------ 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/clj/com/rpl/specter.cljx b/src/clj/com/rpl/specter.cljx index 690930d..a93e01e 100644 --- a/src/clj/com/rpl/specter.cljx +++ b/src/clj/com/rpl/specter.cljx @@ -218,24 +218,20 @@ ))) (defpath - submap* + ^{:doc "Navigates to the specified submap (using select-keys). + In a transform, that submap in the original map is changed to the new + value of the submap."} + submap [m-keys] (select* [this structure next-fn] - (next-fn (merge (zipmap m-keys (repeat nil)) (select-keys structure m-keys)))) + (next-fn (select-keys structure m-keys))) (transform* [this structure next-fn] - (let [submap (merge (zipmap m-keys (repeat nil)) (select-keys structure m-keys)) + (let [submap (select-keys structure m-keys) newmap (next-fn submap)] - (merge (apply dissoc structure m-keys) + (merge (reduce dissoc structure m-keys) newmap)))) -(defn submap - "Navigates to the specified submap (by attempting a get for each key). - In a transform, that submap in the original map is changed to the new - value of the submap." - [& m-keys] - (submap* m-keys)) - (defpath walker [afn] diff --git a/test/com/rpl/specter/core_test.cljx b/test/com/rpl/specter/core_test.cljx index 145db2f..8a8130c 100644 --- a/test/com/rpl/specter/core_test.cljx +++ b/test/com/rpl/specter/core_test.cljx @@ -574,16 +574,16 @@ )))) (deftest submap-test - (is (= [{:foo 1, :baz nil}] - (s/select [(s/submap :foo :baz)] {:foo 1 :bar 2}))) + (is (= [{:foo 1}] + (s/select [(s/submap [:foo :baz])] {:foo 1 :bar 2}))) (is (= {:foo 1, :barry 1} - (s/setval [(s/submap :bar)] {:barry 1} {:foo 1 :bar 2}))) - (is (= {:bar 1, :foo 2, :baz nil} - (s/transform [(s/submap :foo :baz) s/ALL s/LAST (comp not nil?)] inc {:foo 1 :bar 1}))) + (s/setval [(s/submap [:bar])] {:barry 1} {:foo 1 :bar 2}))) + (is (= {:bar 1, :foo 2} + (s/transform [(s/submap [:foo :baz]) s/ALL s/LAST] inc {:foo 1 :bar 1}))) (is (= {:a {:new 1} :c {:new 1 :old 1}} - (s/setval [s/ALL s/LAST (s/submap)] {:new 1} {:a nil, :c {:old 1}})))) + (s/setval [s/ALL s/LAST (s/submap [])] {:new 1} {:a nil, :c {:old 1}})))) (deftest nil->val-test (is (= {:a #{:b}}