added cond-path and if-path selectors
This commit is contained in:
parent
6ba23bc438
commit
da2019b07b
3 changed files with 80 additions and 12 deletions
|
|
@ -11,12 +11,8 @@
|
||||||
|
|
||||||
;; Selector functions
|
;; Selector functions
|
||||||
|
|
||||||
(defn compiled-select
|
(def ^{:doc "Version of select that takes in a selector pre-compiled with comp-paths"}
|
||||||
"Version of select that takes in a selector pre-compiled with comp-paths"
|
compiled-select compiled-select*)
|
||||||
[^com.rpl.specter.impl.TransformFunctions tfns structure]
|
|
||||||
(let [^com.rpl.specter.impl.ExecutorFunctions ex (.executors tfns)]
|
|
||||||
((.select-executor ex) (.selector tfns) structure)
|
|
||||||
))
|
|
||||||
|
|
||||||
(defn select
|
(defn select
|
||||||
"Navigates to and returns a sequence of all the elements specified by the selector."
|
"Navigates to and returns a sequence of all the elements specified by the selector."
|
||||||
|
|
@ -63,12 +59,9 @@
|
||||||
|
|
||||||
;; Update functions
|
;; Update functions
|
||||||
|
|
||||||
(defn compiled-update
|
|
||||||
"Version of update that takes in a selector pre-compiled with comp-paths"
|
(def ^{:doc "Version of update that takes in a selector pre-compiled with comp-paths"}
|
||||||
[^com.rpl.specter.impl.TransformFunctions tfns update-fn structure]
|
compiled-update compiled-update*)
|
||||||
(let [^com.rpl.specter.impl.ExecutorFunctions ex (.executors tfns)]
|
|
||||||
((.update-executor ex) (.updater tfns) update-fn structure)
|
|
||||||
))
|
|
||||||
|
|
||||||
(defn update
|
(defn update
|
||||||
"Navigates to each value specified by the selector and replaces it by the result of running
|
"Navigates to each value specified by the selector and replaces it by the result of running
|
||||||
|
|
@ -190,3 +183,22 @@
|
||||||
(update [:a :b (putval 3)] + some-map)"
|
(update [:a :b (putval 3)] + some-map)"
|
||||||
[val]
|
[val]
|
||||||
(->PutValCollector val))
|
(->PutValCollector val))
|
||||||
|
|
||||||
|
(defn cond-path
|
||||||
|
"Takes in alternating cond-fn selector cond-fn selector...
|
||||||
|
Tests the structure on the cond-fn, and if it matches uses the following selector for
|
||||||
|
the rest of the selector. Otherwise, it moves on to the next selector. If nothing
|
||||||
|
matches, then the structure is not selected."
|
||||||
|
[& conds]
|
||||||
|
(->> conds
|
||||||
|
(partition 2)
|
||||||
|
(map (fn [[c p]] [c (comp-paths* p)]))
|
||||||
|
doall
|
||||||
|
->ConditionalPath
|
||||||
|
))
|
||||||
|
|
||||||
|
(defn if-path
|
||||||
|
"Like cond-path, but with if semantics."
|
||||||
|
([cond-fn if-path] (cond-path cond-fn if-path))
|
||||||
|
([cond-fn if-path else-path]
|
||||||
|
(cond-path cond-fn if-path (fn [_] true) else-path)))
|
||||||
|
|
|
||||||
|
|
@ -469,3 +469,39 @@
|
||||||
(update* [this structure next-fn]
|
(update* [this structure next-fn]
|
||||||
(next-fn structure)
|
(next-fn structure)
|
||||||
))
|
))
|
||||||
|
|
||||||
|
(defn compiled-select*
|
||||||
|
[^com.rpl.specter.impl.TransformFunctions tfns structure]
|
||||||
|
(let [^com.rpl.specter.impl.ExecutorFunctions ex (.executors tfns)]
|
||||||
|
((.select-executor ex) (.selector tfns) structure)
|
||||||
|
))
|
||||||
|
|
||||||
|
(defn compiled-update*
|
||||||
|
[^com.rpl.specter.impl.TransformFunctions tfns update-fn structure]
|
||||||
|
(let [^com.rpl.specter.impl.ExecutorFunctions ex (.executors tfns)]
|
||||||
|
((.update-executor ex) (.updater tfns) update-fn structure)
|
||||||
|
))
|
||||||
|
|
||||||
|
(deftype ConditionalPath [cond-pairs])
|
||||||
|
|
||||||
|
(defn- retrieve-selector [cond-pairs structure]
|
||||||
|
(->> cond-pairs
|
||||||
|
(drop-while (fn [[c-fn _]] (not (c-fn structure))))
|
||||||
|
first
|
||||||
|
second
|
||||||
|
))
|
||||||
|
|
||||||
|
;;TODO: test nothing matches case
|
||||||
|
(extend-protocol StructurePath
|
||||||
|
ConditionalPath
|
||||||
|
(select* [this structure next-fn]
|
||||||
|
(if-let [selector (retrieve-selector (.cond-pairs this) structure)]
|
||||||
|
(->> (compiled-select* selector structure)
|
||||||
|
(mapcat next-fn)
|
||||||
|
doall)))
|
||||||
|
(update* [this structure next-fn]
|
||||||
|
(if-let [selector (retrieve-selector (.cond-pairs this) structure)]
|
||||||
|
(compiled-update* selector next-fn structure)
|
||||||
|
structure
|
||||||
|
)))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -295,3 +295,23 @@
|
||||||
(select [(comp-paths) k1 k2] m)
|
(select [(comp-paths) k1 k2] m)
|
||||||
(select [k1 (comp-paths) k2] m)
|
(select [k1 (comp-paths) k2] m)
|
||||||
)))
|
)))
|
||||||
|
|
||||||
|
(deftest cond-path-test
|
||||||
|
(is (= [4 2 6 8 10]
|
||||||
|
(select [ALL (cond-path even? [(view inc) (view inc)]
|
||||||
|
#(= 3 %) (view dec))]
|
||||||
|
[1 2 3 4 5 6 7 8])))
|
||||||
|
(is (empty? (select (if-path odd? (view inc)) 2)))
|
||||||
|
(is (= [6 2 10 6 14]
|
||||||
|
(update [(putval 2)
|
||||||
|
ALL
|
||||||
|
(if-path odd? [(view inc) (view inc)] (view dec))]
|
||||||
|
*
|
||||||
|
[1 2 3 4 5]
|
||||||
|
)))
|
||||||
|
(is (= 2
|
||||||
|
(update [(putval 2)
|
||||||
|
(if-path odd? (view inc))]
|
||||||
|
*
|
||||||
|
2)))
|
||||||
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue