add multi-path implementation

This commit is contained in:
Nathan Marz 2015-06-25 16:30:27 -04:00
parent dc1da8dfcd
commit 6a2afccbfd
3 changed files with 42 additions and 0 deletions

View file

@ -203,3 +203,9 @@
([cond-fn if-path] (cond-path cond-fn if-path))
([cond-fn if-path else-path]
(cond-path cond-fn if-path nil else-path)))
(defn multi-path
"A path that branches on multiple paths. For updates,
applies updates to the paths in order."
[& paths]
(->MultiPath (->> paths (map comp-paths*) doall)))

View file

@ -47,6 +47,7 @@
(defprotocol CoerceTransformFunctions
(coerce-path [this]))
(defn no-prot-error-str [obj]
(str "Protocol implementation cannot be found for object.
Extending Specter protocols should not be done inline in a deftype definition
@ -519,3 +520,21 @@
structure
)))
(deftype MultiPath [paths])
(extend-protocol StructurePath
MultiPath
(select* [this structure next-fn]
(->> (.paths this)
(mapcat #(compiled-select* % structure))
(mapcat next-fn)
doall
))
(transform* [this structure next-fn]
(reduce
(fn [structure selector]
(compiled-transform* selector next-fn structure))
structure
(.paths this))
))

View file

@ -345,3 +345,20 @@
(= (select (if-path [k1 pred] k2 k3) m)
(select k m))
))))
(defspec multi-path-test
(for-all+
[k1 (max-size 3 gen/keyword)
k2 (max-size 3 gen/keyword)
m (max-size 5
(gen-map-with-keys
gen/keyword
gen/int
k1
k2))
]
(= (transform (multi-path k1 k2) inc m)
(->> m
(transform k1 inc)
(transform k2 inc)))
))