diff --git a/src/clj/com/rpl/specter.cljx b/src/clj/com/rpl/specter.cljx index 357f57b..a9850ce 100644 --- a/src/clj/com/rpl/specter.cljx +++ b/src/clj/com/rpl/specter.cljx @@ -33,45 +33,33 @@ (def ^{:doc "Version of select that takes in a path pre-compiled with comp-paths"} compiled-select i/compiled-select*) -(defn select +(defn select* "Navigates to and returns a sequence of all the elements specified by the path." [path structure] (compiled-select (i/comp-paths* path) structure)) -(defn compiled-select-one - "Version of select-one that takes in a path pre-compiled with comp-paths" - [path structure] - (let [res (compiled-select path structure)] - (when (> (count res) 1) - (i/throw-illegal "More than one element found for params: " path structure)) - (first res) - )) +(def ^{:doc "Version of select-one that takes in a path pre-compiled with comp-paths"} + compiled-select-one i/compiled-select-one*) -(defn select-one +(defn select-one* "Like select, but returns either one element or nil. Throws exception if multiple elements found" [path structure] (compiled-select-one (i/comp-paths* path) structure)) -(defn compiled-select-one! - "Version of select-one! that takes in a path pre-compiled with comp-paths" - [path structure] - (let [res (compiled-select path structure)] - (when (not= 1 (count res)) (i/throw-illegal "Expected exactly one element for params: " path structure)) - (first res) - )) +(def ^{:doc "Version of select-one! that takes in a path pre-compiled with comp-paths"} + compiled-select-one! i/compiled-select-one!*) -(defn select-one! +(defn select-one!* "Returns exactly one element, throws exception if zero or multiple elements found" [path structure] (compiled-select-one! (i/comp-paths* path) structure)) -(defn compiled-select-first - "Version of select-first that takes in a path pre-compiled with comp-paths" - [path structure] - (first (compiled-select path structure))) +(def ^{:doc "Version of select-first that takes in a path pre-compiled with comp-paths"} + compiled-select-first i/compiled-select-first*) -(defn select-first + +(defn select-first* "Returns first element found. Not any more efficient than select, just a convenience" [path structure] (compiled-select-first (i/comp-paths* path) structure)) @@ -82,42 +70,24 @@ (def ^{:doc "Version of transform that takes in a path pre-compiled with comp-paths"} compiled-transform i/compiled-transform*) -(defn transform +(defn transform* "Navigates to each value specified by the path and replaces it by the result of running the transform-fn on it" [path transform-fn structure] (compiled-transform (i/comp-paths* path) transform-fn structure)) -(defn compiled-setval - "Version of setval that takes in a path pre-compiled with comp-paths" - [path val structure] - (compiled-transform path (fn [_] val) structure)) +(def ^{:doc "Version of setval that takes in a path precompiled with comp-paths"} + compiled-setval i/compiled-setval*) -(defn setval +(defn setval* "Navigates to each value specified by the path and replaces it by val" [path val structure] (compiled-setval (i/comp-paths* path) val structure)) -(defn compiled-replace-in - "Version of replace-in that takes in a path pre-compiled with comp-paths" - [path transform-fn structure & {:keys [merge-fn] :or {merge-fn concat}}] - (let [state (i/mutable-cell nil)] - [(compiled-transform path - (fn [& args] - (let [res (apply transform-fn args)] - (if res - (let [[ret user-ret] res] - (->> user-ret - (merge-fn (i/get-cell state)) - (i/set-cell! state)) - ret) - (last args) - ))) - structure) - (i/get-cell state)] - )) +(def ^{:doc "Version of replace-in that takes in a path precompiled with comp-paths"} + compiled-replace-in i/compiled-replace-in*) -(defn replace-in +(defn replace-in* "Similar to transform, except returns a pair of [transformed-structure sequence-of-user-ret]. The transform-fn in this case is expected to return [ret user-ret]. ret is what's used to transform the data structure, while user-ret will be added to the user-ret sequence diff --git a/src/clj/com/rpl/specter/impl.cljx b/src/clj/com/rpl/specter/impl.cljx index a0911f3..18f4cd3 100644 --- a/src/clj/com/rpl/specter/impl.cljx +++ b/src/clj/com/rpl/specter/impl.cljx @@ -753,7 +753,7 @@ ;; - could extend this to see if it contains nested function calls which ;; are only on constants (do - (swap! params-atom concat ps) + (swap! params-atom #(vec (concat % ps))) vv ) @@ -776,9 +776,16 @@ )) :else - (if (valid-navigator? p) - p - (magic-fail! "Constant " p " is not a valid navigator")) + (cond (set? p) + (do (swap! params-atom conj p) + pred*) + + (keyword? p) + p + + :else + (magic-fail! "Code " p " is not a valid navigator or can't be factored") + ) ))) (defn magic-precompilation [prepared-path used-locals] @@ -813,6 +820,43 @@ )) +(defn compiled-select-one* [path structure] + (let [res (compiled-select* path structure)] + (when (> (count res) 1) + (throw-illegal "More than one element found for params: " path structure)) + (first res) + )) + +(defn compiled-select-one!* [path structure] + (let [res (compiled-select* path structure)] + (when (not= 1 (count res)) (throw-illegal "Expected exactly one element for params: " path structure)) + (first res) + )) + +(defn compiled-select-first* [path structure] + (first (compiled-select* path structure))) + +(defn compiled-setval* [path val structure] + (compiled-transform* path (fn [_] val) structure)) + +(defn compiled-replace-in* + [path transform-fn structure & {:keys [merge-fn] :or {merge-fn concat}}] + (let [state (mutable-cell nil)] + [(compiled-transform* path + (fn [& args] + (let [res (apply transform-fn args)] + (if res + (let [[ret user-ret] res] + (->> user-ret + (merge-fn (get-cell state)) + (set-cell! state)) + ret) + (last args) + ))) + structure) + (get-cell state)] + )) + #+clj (defn extend-protocolpath* [protpath protpath-prot extensions] (let [extensions (partition 2 extensions) diff --git a/src/clj/com/rpl/specter/macros.clj b/src/clj/com/rpl/specter/macros.clj index fc2206e..b891ed2 100644 --- a/src/clj/com/rpl/specter/macros.clj +++ b/src/clj/com/rpl/specter/macros.clj @@ -341,11 +341,11 @@ ) :else - path + `(quote ~path) )) ;; still possible to mess this up with alter-var-root -(defmacro ic! [& path] ; "inline cache" +(defmacro path [& path] ; "inline cache" (let [local-syms (-> &env keys set) used-locals (vec (i/walk-select local-syms vector path)) prepared-path (ic-prepare-path local-syms (walk/macroexpand-all (vec path))) @@ -383,3 +383,26 @@ (i/comp-paths* ~(vec path)) )) )) + +(defmacro select [apath structure] + `(i/compiled-select* (path ~apath) ~structure)) + +(defmacro select-one! [apath structure] + `(i/compiled-select-one!* (path ~apath) ~structure)) + +(defmacro select-one [apath structure] + `(i/compiled-select-one* (path ~apath) ~structure)) + +(defmacro select-first [apath structure] + `(i/compiled-select-first* (path ~apath) ~structure)) + +(defmacro transform [apath transform-fn structure] + `(i/compiled-transform* (path ~apath) ~transform-fn ~structure)) + +(defmacro setval [apath aval structure] + `(i/compiled-setval* (path ~apath) ~aval ~structure)) + +(defmacro replace-in + [apath transform-fn structure & args] + `(i/compiled-replace-in* (path ~apath) ~transform-fn ~structure ~@args)) + diff --git a/test/com/rpl/specter/core_test.cljx b/test/com/rpl/specter/core_test.cljx index 08de3dd..d1ebab5 100644 --- a/test/com/rpl/specter/core_test.cljx +++ b/test/com/rpl/specter/core_test.cljx @@ -5,14 +5,16 @@ [com.rpl.specter.cljs-test-helpers :refer [for-all+]] [com.rpl.specter.macros :refer [paramsfn defprotocolpath defnav extend-protocolpath - nav declarepath providepath]]) + nav declarepath providepath select select-one select-one! + select-first transform setval replace-in]]) (:use #+clj [clojure.test :only [deftest is]] #+clj [clojure.test.check.clojure-test :only [defspec]] #+clj [com.rpl.specter.test-helpers :only [for-all+]] #+clj [com.rpl.specter.macros :only [paramsfn defprotocolpath defnav extend-protocolpath - nav declarepath providepath]] + nav declarepath providepath select select-one select-one! + select-first transform setval replace-in]] ) @@ -46,7 +48,7 @@ v (gen/vector (limit-size 5 (gen-map-with-keys gen/keyword gen/int kw))) pred (gen/elements [odd? even?])] - (= (s/select [s/ALL kw pred] v) + (= (select [s/ALL kw pred] v) (->> v (map kw) (filter pred)) ))) @@ -55,45 +57,45 @@ [v (gen/vector gen/int) pred (gen/elements [odd? even?]) pos (gen/elements [[s/FIRST first] [s/LAST last]])] - (= (s/select-one [(s/filterer pred) (first pos)] v) + (= (select-one [(s/filterer pred) (first pos)] v) (->> v (filter pred) ((last pos))) ))) (defspec select-all-on-map (for-all+ [m (limit-size 5 (gen/map gen/keyword gen/int))] - (= (s/select [s/ALL s/LAST] m) + (= (select [s/ALL s/LAST] m) (for [[k v] m] v)) )) (deftest select-one-test - (is (thrown? #+clj Exception #+cljs js/Error (s/select-one [s/ALL even?] [1 2 3 4]))) - (is (= 1 (s/select-one [s/ALL odd?] [2 4 1 6]))) + (is (thrown? #+clj Exception #+cljs js/Error (select-one [s/ALL even?] [1 2 3 4]))) + (is (= 1 (select-one [s/ALL odd?] [2 4 1 6]))) ) (deftest select-first-test - (is (= 7 (s/select-first [(s/filterer odd?) s/ALL #(> % 4)] [3 4 2 3 7 5 9 8]))) - (is (nil? (s/select-first [s/ALL even?] [1 3 5 9]))) + (is (= 7 (select-first [(s/filterer odd?) s/ALL #(> % 4)] [3 4 2 3 7 5 9 8]))) + (is (nil? (select-first [s/ALL even?] [1 3 5 9]))) ) (defspec transform-all-on-map (for-all+ [m (limit-size 5 (gen/map gen/keyword gen/int))] - (= (s/transform [s/ALL s/LAST] inc m) + (= (transform [s/ALL s/LAST] inc m) (into {} (for [[k v] m] [k (inc v)])) ))) (defspec transform-all (for-all+ [v (gen/vector gen/int)] - (let [v2 (s/transform [s/ALL] inc v)] + (let [v2 (transform [s/ALL] inc v)] (and (vector? v2) (= v2 (map inc v))) ))) (defspec transform-all-list (for-all+ [v (gen/list gen/int)] - (let [v2 (s/transform [s/ALL] inc v)] + (let [v2 (transform [s/ALL] inc v)] (and (seq? v2) (= v2 (map inc v))) ))) @@ -102,7 +104,7 @@ [v (gen/vector gen/int) pred (gen/elements [odd? even?]) action (gen/elements [inc dec])] - (let [v2 (s/transform [s/ALL pred] action v)] + (let [v2 (transform [s/ALL pred] action v)] (= v2 (map (fn [v] (if (pred v) (action v) v)) v)) ))) @@ -110,7 +112,7 @@ (for-all+ [v (gen/not-empty (gen/vector gen/int)) pred (gen/elements [inc dec])] - (let [v2 (s/transform [s/LAST] pred v)] + (let [v2 (transform [s/LAST] pred v)] (= v2 (concat (butlast v) [(pred (last v))])) ))) @@ -118,7 +120,7 @@ (for-all+ [v (gen/not-empty (gen/vector gen/int)) pred (gen/elements [inc dec])] - (let [v2 (s/transform [s/FIRST] pred v)] + (let [v2 (transform [s/FIRST] pred v)] (= v2 (concat [(pred (first v))] (rest v) )) ))) @@ -129,8 +131,8 @@ pred (gen/elements [even? odd?]) updater (gen/elements [inc dec])] (let [v (into target-type s) - v2 (s/transform [(s/filterer pred) s/ALL] updater v) - v3 (s/transform [s/ALL pred] updater v)] + v2 (transform [(s/filterer pred) s/ALL] updater v) + v3 (transform [s/ALL pred] updater v)] (and (= v2 v3) (= (type v2) (type v3))) ))) @@ -140,7 +142,7 @@ kw2 gen/keyword m (limit-size 10 (gen-map-with-keys gen/keyword gen/int kw1 kw2)) pred (gen/elements [odd? even?])] - (= (s/transform [(s/collect-one kw2) kw1 pred] + m) + (= (transform [(s/collect-one kw2) kw1 pred] + m) (if (pred (kw1 m)) (assoc m kw1 (+ (kw1 m) (kw2 m))) m @@ -157,7 +159,7 @@ (for-all+ [pred (gen/elements [odd? even?]) v (gen/such-that #(some pred %) (gen/vector gen/int))] - (let [v2 (s/transform [(s/filterer pred) s/LAST] inc v) + (let [v2 (transform [(s/filterer pred) s/LAST] inc v) differing-elems (differing-elements v v2)] (and (= (count v2) (count v)) (= (count differing-elems) 1) @@ -175,7 +177,7 @@ (gen-map-with-keys gen/keyword gen/int k2) k1)) pred (gen/elements [inc dec])] - (let [m2 (s/transform [k1 k2] pred m1)] + (let [m2 (transform [k1 k2] pred m1)] (and (= (assoc-in m1 [k1 k2] nil) (assoc-in m2 [k1 k2] nil)) (= (pred (get-in m1 [k1 k2])) (get-in m2 [k1 k2]))) ))) @@ -189,7 +191,7 @@ (map (fn [v] [v v])) (apply concat)) user-ret (if (empty? user-ret) nil user-ret)] - (= (s/replace-in [s/ALL even?] (fn [v] [(inc v) [v v]]) v) + (= (replace-in [s/ALL even?] (fn [v] [(inc v) [v v]]) v) [res user-ret] )))) @@ -199,7 +201,7 @@ (let [res (->> v (map (fn [v] (if (even? v) (inc v) v)))) last-even (->> v (filter even?) last) user-ret (if last-even {:a last-even})] - (= (s/replace-in [s/ALL even?] (fn [v] [(inc v) v]) v :merge-fn (fn [curr new] + (= (replace-in [s/ALL even?] (fn [v] [(inc v) v]) v :merge-fn (fn [curr new] (assoc curr :a new))) [res user-ret] )))) @@ -208,8 +210,8 @@ (for-all+ [v (gen/vector gen/int) v2 (gen/vector gen/int)] - (let [b (s/setval s/BEGINNING v2 v) - e (s/setval s/END v2 v)] + (let [b (setval s/BEGINNING v2 v) + e (setval s/END v2 v)] (and (= b (concat v2 v)) (= e (concat v v2))) ))) @@ -224,29 +226,29 @@ predcount (fn [pred v] (->> v (filter pred) count)) even-count (partial predcount even?) odd-count (partial predcount odd?) - b (s/transform (s/srange b e) (fn [r] (filter odd? r)) v)] + b (transform (s/srange b e) (fn [r] (filter odd? r)) v)] (and (= (odd-count v) (odd-count b)) (= (+ (even-count b) (even-count sv)) (even-count v))) ))) (deftest structure-path-directly-test - (is (= 3 (s/select-one :b {:a 1 :b 3}))) - (is (= 5 (s/select-one (s/comp-paths :a :b) {:a {:b 5}}))) + (is (= 3 (select-one :b {:a 1 :b 3}))) + (is (= 5 (select-one (s/comp-paths :a :b) {:a {:b 5}}))) ) (deftest atom-test - (let [v (s/transform s/ATOM inc (atom 1))] + (let [v (transform s/ATOM inc (atom 1))] (is (instance? clojure.lang.Atom v)) - (is (= 2 (s/select-one s/ATOM v) @v)))) + (is (= 2 (select-one s/ATOM v) @v)))) (defspec view-test (for-all+ [i gen/int afn (gen/elements [inc dec])] - (= (first (s/select (s/view afn) i)) + (= (first (select (s/view afn) i)) (afn i) - (s/transform (s/view afn) identity i) + (transform (s/view afn) identity i) ))) (defspec must-test @@ -257,11 +259,11 @@ op (gen/elements [inc dec]) ] (let [m (dissoc m k2)] - (and (= (s/transform (s/must k1) op m) - (s/transform (s/keypath k1) op m)) - (= (s/transform (s/must k2) op m) m) - (= (s/select (s/must k1) m) (s/select (s/keypath k1) m)) - (empty? (s/select (s/must k2) m)) + (and (= (transform (s/must k1) op m) + (transform (s/keypath k1) op m)) + (= (transform (s/must k2) op m) m) + (= (select (s/must k1) m) (select (s/keypath k1) m)) + (empty? (select (s/must k2) m)) )))) (defspec parser-test @@ -270,15 +272,15 @@ afn (gen/elements [inc dec #(* % 2)]) bfn (gen/elements [inc dec #(* % 2)]) cfn (gen/elements [inc dec #(* % 2)])] - (and (= (s/select-one! (s/parser afn bfn) i) + (and (= (select-one! (s/parser afn bfn) i) (afn i)) - (= (s/transform (s/parser afn bfn) cfn i) + (= (transform (s/parser afn bfn) cfn i) (-> i afn cfn bfn)) ))) (deftest selected?-test (is (= [[1 3 5] [2 :a] [7 11 4 2 :a] [10 1 :a] []] - (s/setval [s/ALL (s/selected? s/ALL even?) s/END] + (setval [s/ALL (s/selected? s/ALL even?) s/END] [:a] [[1 3 5] [2] [7 11 4 2] [10 1] []] )))) @@ -287,19 +289,19 @@ (for-all+ [i gen/int afn (gen/elements [inc dec])] - (and (= [i] (s/select nil i)) - (= (afn i) (s/transform nil afn i))))) + (and (= [i] (select nil i)) + (= (afn i) (transform nil afn i))))) (deftest nil-comp-test - (is (= [5] (s/select (com.rpl.specter.impl/comp-paths* nil) 5)))) + (is (= [5] (select (com.rpl.specter.impl/comp-paths* nil) 5)))) (defspec putval-test (for-all+ [kw gen/keyword m (limit-size 10 (gen-map-with-keys gen/keyword gen/int kw)) c gen/int] - (= (s/transform [(s/putval c) kw] + m) - (s/transform [kw (s/putval c)] + m) + (= (transform [(s/putval c) kw] + m) + (transform [kw (s/putval c)] + m) (assoc m kw (+ c (get m kw))) ))) @@ -307,11 +309,11 @@ (for-all+ [v (gen/vector gen/int)] (= [v] - (s/select [] v) - (s/select nil v) - (s/select (s/comp-paths) v) - (s/select (s/comp-paths nil) v) - (s/select [nil nil nil] v) + (select [] v) + (select nil v) + (select (s/comp-paths) v) + (select (s/comp-paths nil) v) + (select [nil nil nil] v) ))) (defspec empty-selector-transform-test @@ -319,22 +321,22 @@ [kw gen/keyword m (limit-size 10 (gen-map-with-keys gen/keyword gen/int kw))] (and (= m - (s/transform nil identity m) - (s/transform [] identity m) - (s/transform (s/comp-paths []) identity m) - (s/transform (s/comp-paths nil nil) identity m) + (transform nil identity m) + (transform [] identity m) + (transform (s/comp-paths []) identity m) + (transform (s/comp-paths nil nil) identity m) ) - (= (s/transform kw inc m) - (s/transform [nil kw] inc m) - (s/transform (s/comp-paths kw nil) inc m) - (s/transform (s/comp-paths nil kw nil) inc m) + (= (transform kw inc m) + (transform [nil kw] inc m) + (transform (s/comp-paths kw nil) inc m) + (transform (s/comp-paths nil kw nil) inc m) )))) (deftest compose-empty-comp-path-test (let [m {:a 1}] (is (= [1] - (s/select [:a (s/comp-paths)] m) - (s/select [(s/comp-paths) :a] m) + (select [:a (s/comp-paths)] m) + (select [(s/comp-paths) :a] m) )))) (defspec mixed-selector-test @@ -347,28 +349,28 @@ (gen-map-with-keys gen/keyword gen/int k2) k1))] (= [(-> m k1 k2)] - (s/select [k1 (s/comp-paths k2)] m) - (s/select [(s/comp-paths k1) k2] m) - (s/select [(s/comp-paths k1 k2) nil] m) - (s/select [(s/comp-paths) k1 k2] m) - (s/select [k1 (s/comp-paths) k2] m) + (select [k1 (s/comp-paths k2)] m) + (select [(s/comp-paths k1) k2] m) + (select [(s/comp-paths k1 k2) nil] m) + (select [(s/comp-paths) k1 k2] m) + (select [k1 (s/comp-paths) k2] m) ))) (deftest cond-path-test (is (= [4 2 6 8 10] - (s/select [s/ALL (s/cond-path even? [(s/view inc) (s/view inc)] + (select [s/ALL (s/cond-path even? [(s/view inc) (s/view inc)] #(= 3 %) (s/view dec))] [1 2 3 4 5 6 7 8]))) - (is (empty? (s/select (s/if-path odd? (s/view inc)) 2))) + (is (empty? (select (s/if-path odd? (s/view inc)) 2))) (is (= [6 2 10 6 14] - (s/transform [(s/putval 2) + (transform [(s/putval 2) s/ALL (s/if-path odd? [(s/view inc) (s/view inc)] (s/view dec))] * [1 2 3 4 5] ))) (is (= 2 - (s/transform [(s/putval 2) + (transform [(s/putval 2) (s/if-path odd? (s/view inc))] * 2))) @@ -391,10 +393,10 @@ (let [v1 (get m k1) k (if (pred v1) k2 k3)] (and - (= (s/transform (s/if-path [k1 pred] k2 k3) inc m) - (s/transform k inc m)) - (= (s/select (s/if-path [k1 pred] k2 k3) m) - (s/select k m)) + (= (transform (s/if-path [k1 pred] k2 k3) inc m) + (transform k inc m)) + (= (select (s/if-path [k1 pred] k2 k3) m) + (select k m)) )))) (defspec multi-path-test @@ -408,17 +410,17 @@ k1 k2)) ] - (= (s/transform (s/multi-path k1 k2) inc m) + (= (transform (s/multi-path k1 k2) inc m) (->> m - (s/transform k1 inc) - (s/transform k2 inc))) + (transform k1 inc) + (transform k2 inc))) )) (deftest empty-pos-transform - (is (empty? (s/select s/FIRST []))) - (is (empty? (s/select s/LAST []))) - (is (= [] (s/transform s/FIRST inc []))) - (is (= [] (s/transform s/LAST inc []))) + (is (empty? (select s/FIRST []))) + (is (empty? (select s/LAST []))) + (is (= [] (transform s/FIRST inc []))) + (is (= [] (transform s/LAST inc []))) ) (defspec set-filter-test @@ -427,12 +429,12 @@ k2 (gen/such-that #(not= k1 %) gen/keyword) k3 (gen/such-that (complement #{k1 k2}) gen/keyword) v (gen/vector (gen/elements [k1 k2 k3]))] - (= (filter #{k1 k2} v) (s/select [s/ALL #{k1 k2}] v)) + (= (filter #{k1 k2} v) (select [s/ALL #{k1 k2}] v)) )) (deftest nil-select-one-test - (is (= nil (s/select-one! s/ALL [nil]))) - (is (thrown? #+clj Exception #+cljs js/Error (s/select-one! s/ALL []))) + (is (= nil (select-one! s/ALL [nil]))) + (is (thrown? #+clj Exception #+cljs js/Error (select-one! s/ALL []))) ) @@ -441,8 +443,8 @@ [v (gen/vector gen/int) pred (gen/elements [even? odd?]) op (gen/elements [inc dec])] - (= (s/select-one (s/transformed [s/ALL pred] op) v) - (s/transform [s/ALL pred] op v)) + (= (select-one (s/transformed [s/ALL pred] op) v) + (transform [s/ALL pred] op v)) )) (defspec basic-parameterized-composition-test @@ -457,8 +459,8 @@ pred (gen/elements [inc dec])] (let [p (s/comp-paths s/keypath s/keypath)] (and - (= (s/compiled-select (p k1 k2) m1) (s/select [k1 k2] m1)) - (= (s/compiled-transform (p k1 k2) pred m1) (s/transform [k1 k2] pred m1)) + (= (s/compiled-select (p k1 k2) m1) (select [k1 k2] m1)) + (= (s/compiled-transform (p k1 k2) pred m1) (transform [k1 k2] pred m1)) )))) (defspec various-orders-comp-test @@ -526,8 +528,8 @@ {:a [{:c 3}]} {:a [{:b [{:c 7}] :e [1]}]}] ] - (is (= (s/select p2 data) - (s/select p3 data) + (is (= (select p2 data) + (select p3 data) [[{:a [{:b [{:c 4 :d 5}]}]}]] )) )) @@ -589,11 +591,11 @@ (and (apply = (for [p paths] - (s/select p m) + (select p m) )) (apply = (for [p paths] - (s/transform p updater m) + (transform p updater m) )) )))) @@ -604,8 +606,8 @@ op (gen/elements [inc dec]) comparator (gen/elements [= > <])] (let [cpath (s/comp-paths s/ALL (paramsfn [p] [v] (comparator v p)))] - (= (s/transform (cpath val) op v) - (s/transform [s/ALL #(comparator % val)] op v))) + (= (transform (cpath val) op v) + (transform [s/ALL #(comparator % val)] op v))) )) (defspec subset-test @@ -621,53 +623,53 @@ combined (set/union s1 s2) ss (set/union s2 s3)] (and - (= (s/transform (s/subset s3) identity combined) combined) - (= (s/setval (s/subset s3) #{} combined) (set/difference combined s2)) - (= (s/setval (s/subset s3) s4 combined) (-> combined (set/difference s2) (set/union s4))) + (= (transform (s/subset s3) identity combined) combined) + (= (setval (s/subset s3) #{} combined) (set/difference combined s2)) + (= (setval (s/subset s3) s4 combined) (-> combined (set/difference s2) (set/union s4))) )))) (deftest submap-test (is (= [{:foo 1}] - (s/select [(s/submap [:foo :baz])] {:foo 1 :bar 2}))) + (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}))) + (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}))) + (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}})))) + (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))) + (setval [:a s/NIL->SET (s/subset #{})] #{:b} nil))) (is (= {:a #{:b :c :d}} - (s/setval [:a s/NIL->SET (s/subset #{})] #{:b} {:a #{:c :d}}))) + (setval [:a s/NIL->SET (s/subset #{})] #{:b} {:a #{:c :d}}))) (is (= {:a [:b]} - (s/setval [:a s/NIL->VECTOR s/END] [:b] nil))) + (setval [:a s/NIL->VECTOR s/END] [:b] nil))) ) (defspec void-test (for-all+ [s1 (gen/vector (limit-size 5 gen/int))] (and - (empty? (s/select s/STOP s1)) - (empty? (s/select [s/STOP s/ALL s/ALL s/ALL s/ALL] s1)) - (= s1 (s/transform s/STOP inc s1)) - (= s1 (s/transform [s/ALL s/STOP s/ALL] inc s1)) - (= (s/transform [s/ALL (s/cond-path even? nil odd? s/STOP)] inc s1) - (s/transform [s/ALL even?] inc s1)) + (empty? (select s/STOP s1)) + (empty? (select [s/STOP s/ALL s/ALL s/ALL s/ALL] s1)) + (= s1 (transform s/STOP inc s1)) + (= s1 (transform [s/ALL s/STOP s/ALL] inc s1)) + (= (transform [s/ALL (s/cond-path even? nil odd? s/STOP)] inc s1) + (transform [s/ALL even?] inc s1)) ))) (deftest stay-continue-tests (is (= [[1 2 [:a :b]] [3 [:a :b]] [:a :b [:a :b]]] - (s/setval [(s/stay-then-continue s/ALL) s/END] [[:a :b]] [[1 2] [3]]))) + (setval [(s/stay-then-continue s/ALL) s/END] [[:a :b]] [[1 2] [3]]))) (is (= [[1 2 [:a :b]] [3 [:a :b]] [:a :b]] - (s/setval [(s/continue-then-stay s/ALL) s/END] [[:a :b]] [[1 2] [3]]))) + (setval [(s/continue-then-stay s/ALL) s/END] [[:a :b]] [[1 2] [3]]))) (is (= [[1 2 3] 1 3] - (s/select (s/stay-then-continue s/ALL odd?) [1 2 3]))) + (select (s/stay-then-continue s/ALL odd?) [1 2 3]))) (is (= [1 3 [1 2 3]] - (s/select (s/continue-then-stay s/ALL odd?) [1 2 3]))) + (select (s/continue-then-stay s/ALL odd?) [1 2 3]))) ) @@ -682,11 +684,11 @@ (deftest recursive-path-test (is (= [9 1 10 3 1] - (s/select [MyWalker s/ALL number?] + (select [MyWalker s/ALL number?] [:bb [:aa 34 [:abc 10 [:ccc 9 8 [:abc 9 1]]]] [:abc 1 [:abc 3]]]) )) (is (= [:bb [:aa 34 [:abc 11 [:ccc 9 8 [:abc 10 2]]]] [:abc 2 [:abc 4]]] - (s/transform [MyWalker s/ALL number?] inc + (transform [MyWalker s/ALL number?] inc [:bb [:aa 34 [:abc 10 [:ccc 9 8 [:abc 9 1]]]] [:abc 1 [:abc 3]]]) )) ) @@ -700,23 +702,23 @@ [s/LAST (s/params-reset map-key-walker)])]) (deftest recursive-params-path-test - (is (= #{1 2 3} (set (s/select (map-key-walker :aaa) + (is (= #{1 2 3} (set (select (map-key-walker :aaa) {:a {:aaa 3 :b {:c {:aaa 2} :aaa 1}}})))) (is (= {:a {:aaa 4 :b {:c {:aaa 3} :aaa 2}}} - (s/transform (map-key-walker :aaa) inc + (transform (map-key-walker :aaa) inc {:a {:aaa 3 :b {:c {:aaa 2} :aaa 1}}}))) (is (= {:a {:c {:b "X"}}} - (s/setval (map-key-walker :b) "X" {:a {:c {:b {:d 1}}}}))) + (setval (map-key-walker :b) "X" {:a {:c {:b {:d 1}}}}))) ) (deftest recursive-params-composable-path-test (let [p (s/comp-paths s/keypath map-key-walker)] - (is (= [1] (s/select (p 1 :a) [{:a 3} {:a 1} {:a 2}]))) + (is (= [1] (select (p 1 :a) [{:a 3} {:a 1} {:a 2}]))) )) (deftest all-map-test - (is (= {3 3} (s/transform [s/ALL s/FIRST] inc {2 3}))) - (is (= {3 21 4 31} (s/transform [s/ALL s/ALL] inc {2 20 3 30}))) + (is (= {3 3} (transform [s/ALL s/FIRST] inc {2 3}))) + (is (= {3 21 4 31} (transform [s/ALL s/ALL] inc {2 20 3 30}))) ) (declarepath NestedHigherOrderWalker [k]) @@ -730,7 +732,7 @@ (deftest nested-higher-order-walker-test (is (= [:q [:abc :I 3] [:ccc [:abc :I] [:abc :I "a" [:abc :I [:abc :I [:d]]]]]] - (s/setval [(NestedHigherOrderWalker :abc) (s/srange 1 1)] + (setval [(NestedHigherOrderWalker :abc) (s/srange 1 1)] [:I] [:q [:abc 3] [:ccc [:abc] [:abc "a" [:abc [:abc [:d]]]]]] )))) @@ -743,7 +745,7 @@ {k m}) :a (reverse (range 25)))] - (is (= :a (s/select-one (apply path (range 25)) m))) + (is (= :a (select-one (apply path (range 25)) m))) )) ;;TODO: there's a bug in clojurescript that won't allow ;; non function implementations of IFn to have more than 20 arguments @@ -763,11 +765,11 @@ (->User (->Account 50)) (->Family [(->Account 51) (->Account 52)])]] (is (= [30 50 51 52] - (s/select [s/ALL AccountPath :funds] data))) + (select [s/ALL AccountPath :funds] data))) (is (= [(->User (->Account 31)) (->User (->Account 51)) (->Family [(->Account 52) (->Account 53)])] - (s/transform [s/ALL AccountPath :funds] + (transform [s/ALL AccountPath :funds] inc data))) )) @@ -788,11 +790,11 @@ (->LabeledUser {:a (->Account 50)}) (->LabeledFamily {:a [(->Account 51) (->Account 52)]})]] (is (= [30 50 51 52] - (s/select [s/ALL (LabeledAccountPath :a) :funds] data))) + (select [s/ALL (LabeledAccountPath :a) :funds] data))) (is (= [(->LabeledUser {:a (->Account 31)}) (->LabeledUser {:a (->Account 51)}) (->LabeledFamily {:a [(->Account 52) (->Account 53)]})] - (s/transform [s/ALL (LabeledAccountPath :a) :funds] + (transform [s/ALL (LabeledAccountPath :a) :funds] inc data))) )) @@ -813,9 +815,9 @@ #+clj (deftest mixed-rich-regular-protocolpath (is (= [1 2 3 11 21 22 25] - (s/select [CustomWalker number?] [{:a [1 2 :c [3]]} [[[[[[11]]] 21 [22 :c 25]]]]]))) + (select [CustomWalker number?] [{:a [1 2 :c [3]]} [[[[[[11]]] 21 [22 :c 25]]]]]))) (is (= [2 3 [[[4]] :b 0] {:a 4 :b 10}] - (s/transform [CustomWalker number?] inc [1 2 [[[3]] :b -1] {:a 3 :b 10}]))) + (transform [CustomWalker number?] inc [1 2 [[[3]] :b -1] {:a 3 :b 10}]))) ) #+cljs @@ -839,11 +841,11 @@ m1 (gen/map gen/keyword gen/int)] (let [s1 (set v1) q1 (make-queue v1) - v2 (s/transform s/ALL identity v1) - m2 (s/transform s/ALL identity m1) - s2 (s/transform s/ALL identity s1) - l2 (s/transform s/ALL identity l1) - q2 (s/transform s/ALL identity q1)] + v2 (transform s/ALL identity v1) + m2 (transform s/ALL identity m1) + s2 (transform s/ALL identity s1) + l2 (transform s/ALL identity l1) + q2 (transform s/ALL identity q1)] (and (= v1 v2) (= (type v1) (type v2)) diff --git a/test/com/rpl/specter/zipper_test.cljx b/test/com/rpl/specter/zipper_test.cljx index 3e8bd79..fd308ef 100644 --- a/test/com/rpl/specter/zipper_test.cljx +++ b/test/com/rpl/specter/zipper_test.cljx @@ -4,14 +4,16 @@ [cljs.test.check.cljs-test :refer [defspec]] [com.rpl.specter.cljs-test-helpers :refer [for-all+]] [com.rpl.specter.macros - :refer [declarepath providepath]] + :refer [declarepath providepath select select-one select-one! + select-first transform setval replace-in]] ) (:use #+clj [clojure.test :only [deftest is]] #+clj [clojure.test.check.clojure-test :only [defspec]] #+clj [com.rpl.specter.test-helpers :only [for-all+]] #+clj [com.rpl.specter.macros - :only [declarepath providepath]] + :only [declarepath providepath select select-one select-one! + select-first transform setval replace-in]] ) (:require #+clj [clojure.test.check.generators :as gen] #+clj [clojure.test.check.properties :as prop] @@ -25,13 +27,13 @@ (for-all+ [v (gen/not-empty (gen/vector gen/int)) i (gen/vector gen/int)] - (= (s/setval s/END i v) - (s/setval [z/VECTOR-ZIP z/DOWN z/RIGHTMOST z/INNER-RIGHT] i v)) + (= (setval s/END i v) + (setval [z/VECTOR-ZIP z/DOWN z/RIGHTMOST z/INNER-RIGHT] i v)) )) (deftest zipper-multi-insert-test (is (= [1 2 :a :b 3 :a :b 4] - (s/setval [z/VECTOR-ZIP + (setval [z/VECTOR-ZIP z/DOWN z/RIGHT z/RIGHT @@ -40,7 +42,7 @@ [:a :b] [1 2 3 4] ) - (s/setval [z/VECTOR-ZIP + (setval [z/VECTOR-ZIP z/DOWN z/RIGHT z/RIGHT @@ -54,7 +56,7 @@ (deftest zipper-down-up-test (is (= [1 [2 3 5] 6] - (s/transform [z/VECTOR-ZIP + (transform [z/VECTOR-ZIP z/DOWN z/RIGHT z/DOWN @@ -72,11 +74,11 @@ (deftest next-terminate-test (is (= [2 [3 4 [5]] 6] - (s/transform [z/VECTOR-ZIP z/NEXT-WALK z/NODE number?] + (transform [z/VECTOR-ZIP z/NEXT-WALK z/NODE number?] inc [1 [2 3 [4]] 5]))) (is (= [1 [3 [[]] 5]] - (s/setval [z/VECTOR-ZIP + (setval [z/VECTOR-ZIP z/NEXT-WALK (s/selected? z/NODE number? even?) z/NODE-SEQ] @@ -88,18 +90,18 @@ (deftest zipper-nav-stop-test (is (= [1] - (s/transform [z/VECTOR-ZIP z/UP z/NODE] inc [1]))) + (transform [z/VECTOR-ZIP z/UP z/NODE] inc [1]))) (is (= [1] - (s/transform [z/VECTOR-ZIP z/DOWN z/LEFT z/NODE] inc [1]))) + (transform [z/VECTOR-ZIP z/DOWN z/LEFT z/NODE] inc [1]))) (is (= [1] - (s/transform [z/VECTOR-ZIP z/DOWN z/RIGHT z/NODE] inc [1]))) + (transform [z/VECTOR-ZIP z/DOWN z/RIGHT z/NODE] inc [1]))) (is (= [] - (s/transform [z/VECTOR-ZIP z/DOWN z/NODE] inc []))) + (transform [z/VECTOR-ZIP z/DOWN z/NODE] inc []))) ) (deftest find-first-test (is (= [1 [3 [[4]] 5] 6] - (s/setval [z/VECTOR-ZIP + (setval [z/VECTOR-ZIP (z/find-first #(and (number? %) (even? %))) z/NODE-SEQ ] @@ -110,7 +112,7 @@ (deftest nodeseq-expand-test (is (= [2 [2] [[4 4 4]] 4 4 4 6] - (s/transform [z/VECTOR-ZIP + (transform [z/VECTOR-ZIP z/NEXT-WALK (s/selected? z/NODE number? odd?) (s/collect-one z/NODE)