diff --git a/CHANGES.md b/CHANGES.md index ddb4a65..5a66695 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,7 @@ * Transform to `com.rpl.specter/NONE` to remove elements from data structures. Works with `keypath` (for both sequences and maps), `must`, `ALL`, and `MAP-VALS` * Dynamic navs automatically compile sequence returns if completely static * Eliminate reflection warnings for clj (thanks @mpenet) +* Add `with-fresh-collected` higher order navigator ## 0.13.2 diff --git a/src/clj/com/rpl/specter.cljc b/src/clj/com/rpl/specter.cljc index d0dcc58..dd50090 100644 --- a/src/clj/com/rpl/specter.cljc +++ b/src/clj/com/rpl/specter.cljc @@ -974,6 +974,16 @@ (collect-val [this structure] val)) +(defdynamicnav with-fresh-collected + [& path] + (late-bound-richnav [late (late-path path)] + (select* [this vals structure next-fn] + (i/exec-select* late [] structure (fn [_ structure] (next-fn vals structure))) + ) + (transform* [this vals structure next-fn] + (i/exec-transform* late [] structure (fn [_ structure] (next-fn vals structure)))) + )) + (defrichnav ^{:doc "Drops all collected values for subsequent navigation."} DISPENSE diff --git a/test/com/rpl/specter/core_test.cljc b/test/com/rpl/specter/core_test.cljc index 583edcd..f21895d 100644 --- a/test/com/rpl/specter/core_test.cljc +++ b/test/com/rpl/specter/core_test.cljc @@ -1336,3 +1336,25 @@ (is (= (dissoc m 31) (setval [s/MAP-VALS #(= 31 %)] s/NONE m))) (is (= (dissoc m 31) (setval [s/ALL (s/selected? s/LAST #(= 31 %))] s/NONE m))) )) + +(deftest fresh-collected-test + (let [data [{:a 1 :b 2} {:a 3 :b 3}]] + (is (= [[{:a 1 :b 2} 2]] + (select [s/ALL + s/VAL + (s/with-fresh-collected + (s/collect-one :a) + (s/collected? [a] (= a 1))) + :b] + data))) + (is (= [{:a 1 :b 3} {:a 3 :b 3}] + (transform [s/ALL + s/VAL + (s/with-fresh-collected + (s/collect-one :a) + (s/collected? [a] (= a 1))) + :b] + (fn [m v] (+ (:a m) v)) + data + ))) + ))