diff --git a/src/clj/com/rpl/specter.cljx b/src/clj/com/rpl/specter.cljx index c21dae6..4e9ec2c 100644 --- a/src/clj/com/rpl/specter.cljx +++ b/src/clj/com/rpl/specter.cljx @@ -146,6 +146,15 @@ structure )) +(defpath + ^{:doc "Stays navigated at the current point. Essentially a no-op selector."} + STAY + [] + (select* [this structure next-fn] + (next-fn structure)) + (transform* [this structure next-fn] + (next-fn structure))) + (def ALL (comp-paths (i/->AllStructurePath))) (def VAL (i/->ValCollect)) @@ -235,6 +244,30 @@ ancestry)) ))) +(defn stay-then-continue + "Navigates to the current element and then navigates via the provided path. + This can be used to implement pre-order traversal." + [& path] + (fixed-pathed-path [late path] + (select* [this structure next-fn] + (concat (next-fn structure) + (doall (mapcat next-fn (compiled-select late structure))))) + (transform* [this structure next-fn] + (compiled-transform late next-fn (next-fn structure)) + ))) + +(defn continue-then-stay + "Navigates to the provided path and then to the current element. This can be used + to implement post-order traversal." + [& path] + (fixed-pathed-path [late path] + (select* [this structure next-fn] + (concat (doall (mapcat next-fn (compiled-select late structure))) + (next-fn structure))) + (transform* [this structure next-fn] + (next-fn (compiled-transform late next-fn structure)) + ))) + (defpath keypath [key] (select* [this structure next-fn] diff --git a/test/com/rpl/specter/core_test.cljx b/test/com/rpl/specter/core_test.cljx index e8b31cf..8fd08ee 100644 --- a/test/com/rpl/specter/core_test.cljx +++ b/test/com/rpl/specter/core_test.cljx @@ -578,6 +578,17 @@ (s/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]]))) + (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]]))) + (is (= [[1 2 3] 1 3] + (s/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]))) + ) + #+clj (deftest large-params-test (let [path (apply s/comp-paths (repeat 25 s/keypath))