Compare commits

...

2 commits

Author SHA1 Message Date
Nathan Marz
bde18388d7 notes 2015-05-05 09:32:34 -04:00
Nathan Marz
3f26eb1826 let structurepath only execution skip all the val logic 2015-04-27 19:04:25 -04:00
3 changed files with 103 additions and 33 deletions

View file

@ -15,11 +15,7 @@
"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."
[selector structure] [selector structure]
(let [sp (comp-paths* selector)] (let [sp (comp-paths* selector)]
(select-full* sp (exec-select selector structure)
[]
structure
(fn [vals structure]
(if-not (empty? vals) [(conj vals structure)] [structure])))
)) ))
(defn select-one (defn select-one
@ -51,14 +47,8 @@
the update-fn on it" the update-fn on it"
[selector update-fn structure] [selector update-fn structure]
(let [selector (comp-paths* selector)] (let [selector (comp-paths* selector)]
(update-full* selector (exec-update selector update-fn structure)
[] ))
structure
(fn [vals structure]
(if (empty? vals)
(update-fn structure)
(apply update-fn (conj vals structure)))
))))
(defn setval (defn setval
"Navigates to each value specified by the selector and replaces it by val" "Navigates to each value specified by the selector and replaces it by val"

View file

@ -9,14 +9,10 @@
(dotimes [_ iters] (dotimes [_ iters]
(afn)))) (afn))))
(defprotocol CoerceStructureValsPath (defprotocol CoercePath
(coerce-path [this])) (coerce-path [this]))
(extend-protocol CoerceStructureValsPath (extend-protocol CoercePath
com.rpl.specter.protocols.StructureValsPath
(coerce-path [this] this)
com.rpl.specter.protocols.Collector com.rpl.specter.protocols.Collector
(coerce-path [collector] (coerce-path [collector]
(reify StructureValsPath (reify StructureValsPath
@ -28,22 +24,74 @@
;; need to say Object instead of StructurePath so that things like Keyword are properly coerced ;; need to say Object instead of StructurePath so that things like Keyword are properly coerced
Object Object
(coerce-path [spath] (coerce-path [spath]
spath))
(defprotocol CoerceStructureValsPath
(coerce-structure-vals-path [this]))
(extend-protocol CoerceStructureValsPath
com.rpl.specter.protocols.StructureValsPath
(coerce-structure-vals-path [this] this)
com.rpl.specter.protocols.Collector
(coerce-structure-vals-path [this] (coerce-path this))
;; need to say Object instead of StructurePath so that things like Keyword are properly coerced
Object
(coerce-structure-vals-path [spath]
(reify StructureValsPath (reify StructureValsPath
(select-full* [this vals structure next-fn] (select-full* [this vals structure next-fn]
(select* spath structure (fn [structure] (next-fn vals structure)))) (select* spath structure (fn [structure] (next-fn vals structure))))
(update-full* [this vals structure next-fn] (update-full* [this vals structure next-fn]
(update* spath structure (fn [structure] (next-fn vals structure))) (update* spath structure (fn [structure] (next-fn vals structure)))
))) ))))
)
(defn- combine-same-types [[f & _ :as all]]
(cond (extends? StructureValsPath (class f))
all
(extend-protocol StructureValsPathComposer (extends? Collector (class f))
[(reify StructureValsPath
(select-full* [this vals structure next-fn]
(next-fn (reduce conj vals (for [c all] (collect-val c structure))) structure))
(update-full* [this vals structure next-fn]
(next-fn (reduce conj vals (for [c all] (collect-val c structure))) structure))
)]
:else
[(reduce (fn [curr sp]
(reify StructurePath
(select* [this structure next-fn]
(select* sp structure
(fn [structure-next]
(select* curr structure-next next-fn))))
(update* [this structure next-fn]
(update* sp structure
(fn [structure-next]
(update* curr structure-next next-fn))))
))
(reverse all))]))
(defprotocol PathComposer
(comp-paths* [paths]))
(extend-protocol PathComposer
Object Object
(comp-paths* [sp] (comp-paths* [sp]
(coerce-path sp)) (coerce-path sp))
java.util.List java.util.List
(comp-paths* [structure-paths] (comp-paths* [structure-paths]
(reduce (fn [sp-curr sp] (let [combined (->> structure-paths
flatten
(partition-by (fn [e]
(cond (extends? StructureValsPath (class e)) :svalspath
(extends? Collector (class e)) :collector
:else :spath)))
(mapcat combine-same-types))]
(if (= 1 (count combined))
(first combined)
(reduce (fn [sp-curr sp]
(reify StructureValsPath (reify StructureValsPath
(select-full* [this vals structure next-fn] (select-full* [this vals structure next-fn]
(select-full* sp vals structure (select-full* sp vals structure
@ -55,7 +103,35 @@
(fn [vals-next structure-next] (fn [vals-next structure-next]
(update-full* sp-curr vals-next structure-next next-fn)))) (update-full* sp-curr vals-next structure-next next-fn))))
)) ))
(->> structure-paths flatten (map coerce-path) reverse)) (->> structure-paths (map coerce-structure-vals-path) reverse))
))))
(defprotocol Executor
(exec-select [selector structure])
(exec-update [selector update-fn structure]))
(extend-protocol Executor
com.rpl.specter.protocols.StructureValsPath
(exec-select [selector structure]
(select-full* selector
[]
structure
(fn [vals structure]
(if-not (empty? vals) [(conj vals structure)] [structure]))))
(exec-update [selector update-fn structure]
(update-full* selector
[]
structure
(fn [vals structure]
(if (empty? vals)
(update-fn structure)
(apply update-fn (conj vals structure))))))
Object
(exec-select [selector structure]
(select* selector structure (fn [e] [e])))
(exec-update [selector update-fn structure]
(update* selector structure update-fn)
)) ))
;; cell implementation idea taken from prismatic schema library ;; cell implementation idea taken from prismatic schema library
@ -117,8 +193,8 @@
(defn- walk-until [pred on-match-fn structure] (defn- walk-until [pred on-match-fn structure]
(if (pred structure) (if (pred structure)
(on-match-fn structure) (on-match-fn structure)
(walk/walk (partial walk-until pred on-match-fn) identity structure) (walk/walk (partial walk-until pred on-match-fn) identity structure)
)) ))
(defn- fn-invocation? [f] (defn- fn-invocation? [f]
@ -130,7 +206,7 @@
(if (pred structure) (if (pred structure)
(on-match-fn structure) (on-match-fn structure)
(let [ret (walk/walk (partial codewalk-until pred on-match-fn) identity structure)] (let [ret (walk/walk (partial codewalk-until pred on-match-fn) identity structure)]
(if (and (fn-invocation? structure) (fn-invocation? ret)) (if (and (fn-invocation? structure) (fn-invocation? ret))
(with-meta ret (meta structure)) (with-meta ret (meta structure))
ret ret
)))) ))))
@ -159,7 +235,7 @@
[(conj s e) (assoc m pos i)] [(conj s e) (assoc m pos i)]
orig orig
))) )))
[[] {}] [[] {}]
(range (count aseq)) (range (count aseq))
))) )))
@ -269,6 +345,3 @@
(update* [this structure next-fn] (update* [this structure next-fn]
(-> structure view-fn next-fn) (-> structure view-fn next-fn)
)) ))

View file

@ -1,6 +1,10 @@
(ns com.rpl.specter.protocols) (ns com.rpl.specter.protocols)
;;TODO: might be able to speed it up more by having these return a function rather than
;;rely on protocol methods (can then compose functions together directly)
;;so protocol would just be used during composition - what about execution?
;;could have a select-fast function that takes in a selector FUNCTION explicitly
(defprotocol StructureValsPath (defprotocol StructureValsPath
(select-full* [this vals structure next-fn]) (select-full* [this vals structure next-fn])
(update-full* [this vals structure next-fn])) (update-full* [this vals structure next-fn]))
@ -12,5 +16,8 @@
(defprotocol Collector (defprotocol Collector
(collect-val [this structure])) (collect-val [this structure]))
(defprotocol StructureValsPathComposer ;;TODO: Collectors in sequence become a StructureValsPath that does all collection at once
(comp-paths* [paths])) ;;StructurePath in sequence become a single StructurePath
;;any StructureValsPath composed with anything becomes a StructureValsPath
;;TODO: update update/select to be able to execute a StructurePath directly without coercing it
;; - this will avoid MANY layers of indirection and overhead