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

View file

@ -9,14 +9,10 @@
(dotimes [_ iters]
(afn))))
(defprotocol CoerceStructureValsPath
(defprotocol CoercePath
(coerce-path [this]))
(extend-protocol CoerceStructureValsPath
com.rpl.specter.protocols.StructureValsPath
(coerce-path [this] this)
(extend-protocol CoercePath
com.rpl.specter.protocols.Collector
(coerce-path [collector]
(reify StructureValsPath
@ -28,22 +24,74 @@
;; need to say Object instead of StructurePath so that things like Keyword are properly coerced
Object
(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
(select-full* [this vals structure next-fn]
(select* spath structure (fn [structure] (next-fn vals structure))))
(update-full* [this vals structure next-fn]
(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
(comp-paths* [sp]
(coerce-path sp))
java.util.List
(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
(select-full* [this vals structure next-fn]
(select-full* sp vals structure
@ -55,7 +103,35 @@
(fn [vals-next structure-next]
(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
@ -269,6 +345,3 @@
(update* [this structure next-fn]
(-> structure view-fn next-fn)
))

View file

@ -1,6 +1,10 @@
(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
(select-full* [this vals structure next-fn])
(update-full* [this vals structure next-fn]))
@ -12,5 +16,8 @@
(defprotocol Collector
(collect-val [this structure]))
(defprotocol StructureValsPathComposer
(comp-paths* [paths]))
;;TODO: Collectors in sequence become a StructureValsPath that does all collection at once
;;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