diff --git a/src/clj/com/rpl/specter.cljx b/src/clj/com/rpl/specter.cljx index c0802bf..fb564c4 100644 --- a/src/clj/com/rpl/specter.cljx +++ b/src/clj/com/rpl/specter.cljx @@ -256,6 +256,23 @@ ancestry)) ))) +(defn select-view + "Navigates to a sequence that contains the results of (select ...), + but is a view to the original structure that can be transformed." + [& path] + (fixed-pathed-path [late path] + (select* [this structure next-fn] + (next-fn (compiled-select late structure))) + (transform* [this structure next-fn] + (let [select-result (compiled-select late structure) + transformed (next-fn select-result) + values-to-insert (atom transformed)] + (compiled-transform late + (fn [_] (let [next-val (first @values-to-insert)] + (swap! values-to-insert rest) + next-val)) + structure))))) + (defpath keypath [key] (select* [this structure next-fn] (next-fn (get structure key))) diff --git a/test/com/rpl/specter/core_test.cljx b/test/com/rpl/specter/core_test.cljx index d23bd34..15f20e2 100644 --- a/test/com/rpl/specter/core_test.cljx +++ b/test/com/rpl/specter/core_test.cljx @@ -510,6 +510,37 @@ )) )) +(defspec select-view-nested-vectors + (for-all+ + [v1 (gen/vector + (gen/vector gen/int))] + (let [path (s/comp-paths (s/select-view s/ALL s/ALL)) + v2 (s/compiled-transform path reverse v1)] + (and + (= (s/compiled-select path v1) [(flatten v1)]) + (= (flatten v1) (reverse (flatten v2))) + (= (map count v1) (map count v2)))))) + +(defspec select-view-param-test + (for-all+ + [k gen/keyword + v (gen/vector + (limit-size 5 + (gen-map-with-keys + gen/keyword + gen/int + k)))] + (and + (= (s/compiled-select ((s/select-view s/ALL s/keypath) k) v) + [(map k v)]) + (let [v2 (s/compiled-transform ((s/comp-paths (s/select-view s/ALL s/keypath)) k) + reverse + v)] + (and (= (map k v) (reverse (map k v2))) + (= (map #(dissoc % k) v) + (map #(dissoc % k) v2))) ; only key k was touched in any of the maps + )))) + (defspec param-multi-path-test (for-all+ [k1 gen/keyword