diff --git a/CHANGES.md b/CHANGES.md index 5c6aeb8..d92ae84 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,7 @@ ## 1.0.6-SNAPSHOT -* Add `vterminal` that takes in collected vals as vector in first argument rather than spliced into full argument list. +* Add `vtransform` variant of `transform` that takes in collected values as a vector in the first argument rather than spliced into argument list. +* Add `vterminal` that takes in collected vals as vector in first argument rather than spliced into argument list. ## 1.0.5 diff --git a/src/clj/com/rpl/specter.cljc b/src/clj/com/rpl/specter.cljc index 79b7b68..df64701 100644 --- a/src/clj/com/rpl/specter.cljc +++ b/src/clj/com/rpl/specter.cljc @@ -349,6 +349,12 @@ [apath transform-fn structure] `(i/compiled-transform* (path ~apath) ~transform-fn ~structure)) + (defmacro vtransform + "Navigates to each value specified by the path and replaces it by the result of running + the transform-fn on two arguments: the collected values as a vector, and the navigated value." + [apath transform-fn structure] + `(i/compiled-vtransform* (path ~apath) ~transform-fn ~structure)) + (defmacro multi-transform "Just like `transform` but expects transform functions to be specified inline in the path using `terminal` or `vterminal`. Error is thrown if navigation finishes @@ -552,6 +558,10 @@ (def ^{:doc "Version of transform that takes in a path precompiled with comp-paths"} compiled-transform i/compiled-transform*) +(def ^{:doc "Version of vtransform that takes in a path precompiled with comp-paths"} + compiled-vtransform i/compiled-vtransform*) + + (defn transform* "Navigates to each value specified by the path and replaces it by the result of running the transform-fn on it" diff --git a/src/clj/com/rpl/specter/impl.cljc b/src/clj/com/rpl/specter/impl.cljc index 8195273..cdc2a62 100644 --- a/src/clj/com/rpl/specter/impl.cljc +++ b/src/clj/com/rpl/specter/impl.cljc @@ -412,6 +412,9 @@ (fn [vals structure] (terminal* transform-fn vals structure)))) +(defn compiled-vtransform* [nav transform-fn structure] + (exec-transform* nav [] structure transform-fn)) + (defn fn-invocation? [f] (or #?(:clj (instance? clojure.lang.Cons f)) #?(:clj (instance? clojure.lang.LazySeq f)) diff --git a/test/com/rpl/specter/core_test.cljc b/test/com/rpl/specter/core_test.cljc index 2875cc3..68156af 100644 --- a/test/com/rpl/specter/core_test.cljc +++ b/test/com/rpl/specter/core_test.cljc @@ -1656,6 +1656,10 @@ {:a {:b 3}}))) ) +(deftest vtransform-test + (is (= {:a 6} (vtransform [:a (s/putval 2) (s/putval 3)] (fn [vs v] (+ v (reduce + vs))) {:a 1}))) + ) + #?(:clj (do (defprotocolpath FooPP)