prepare for optimized execution of pure structurepaths

This commit is contained in:
Nathan Marz 2015-05-11 10:35:30 -04:00
parent a22df528f0
commit 0767afca61
2 changed files with 59 additions and 25 deletions

View file

@ -13,10 +13,10 @@
(defn compiled-select (defn compiled-select
"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"
[^com.rpl.specter.impl.StructureValsPathFunctions selfns structure] [^com.rpl.specter.impl.TransformFunctions tfns structure]
((.selector selfns) [] structure (let [^com.rpl.specter.impl.ExecutorFunctions ex (.executors tfns)]
(fn [vals structure] ((.select-executor ex) (.selector tfns) structure)
(if-not (empty? vals) [(conj vals structure)] [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."
@ -65,13 +65,10 @@
(defn compiled-update (defn compiled-update
"Version of update that takes in a selector pre-compiled with comp-paths" "Version of update that takes in a selector pre-compiled with comp-paths"
[^com.rpl.specter.impl.StructureValsPathFunctions selfns update-fn structure] [^com.rpl.specter.impl.TransformFunctions tfns update-fn structure]
((.updater selfns) [] structure (let [^com.rpl.specter.impl.ExecutorFunctions ex (.executors tfns)]
(fn [vals structure] ((.update-executor ex) (.updater tfns) update-fn structure)
(if (empty? vals) ))
(update-fn structure)
(apply update-fn (conj vals 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
@ -162,10 +159,11 @@
(extend-type clojure.lang.Keyword (extend-type clojure.lang.Keyword
StructurePath StructurePath
(select* [kw structure next-fn] ;; faster to invoke keyword directly on structure rather than reuse key-select and key-update functions
(key-select kw structure next-fn)) (select* [^clojure.lang.Keyword kw structure next-fn]
(update* [kw structure next-fn] (next-fn (kw structure)))
(key-update kw structure next-fn) (update* [^clojure.lang.Keyword kw structure next-fn]
(assoc structure kw (next-fn (kw structure)))
)) ))
(extend-type clojure.lang.AFn (extend-type clojure.lang.AFn

View file

@ -15,9 +15,36 @@
(dotimes [_ iters] (dotimes [_ iters]
(afn)))) (afn))))
(deftype StructureValsPathFunctions [selector updater]) (deftype ExecutorFunctions [type select-executor update-executor])
(defprotocol CoerceStructureValsPathFunctions (def StructureValsPathExecutor
(->ExecutorFunctions
:svalspath
(fn [selector structure]
(selector [] structure
(fn [vals structure]
(if-not (empty? vals) [(conj vals structure)] [structure]))))
(fn [updater update-fn structure]
(updater [] structure
(fn [vals structure]
(if (empty? vals)
(update-fn structure)
(apply update-fn (conj vals structure))))))
))
(def StructurePathExecutor
(->ExecutorFunctions
:spath
(fn [selector structure]
(selector structure (fn [structure] [structure])))
(fn [updater update-fn structure]
(updater structure update-fn))
))
(deftype TransformFunctions [executors selector updater])
(defprotocol CoerceTransformFunctions
(coerce-path [this])) (coerce-path [this]))
(defn no-prot-error-str [obj] (defn no-prot-error-str [obj]
@ -38,7 +65,8 @@
(let [pimpl (find-protocol-impl! StructureValsPath this) (let [pimpl (find-protocol-impl! StructureValsPath this)
selector (:select-full* pimpl) selector (:select-full* pimpl)
updater (:update-full* pimpl)] updater (:update-full* pimpl)]
(->StructureValsPathFunctions (->TransformFunctions
StructureValsPathExecutor
(fn [vals structure next-fn] (fn [vals structure next-fn]
(selector this vals structure next-fn)) (selector this vals structure next-fn))
(fn [vals structure next-fn] (fn [vals structure next-fn]
@ -53,13 +81,14 @@
afn (fn [vals structure next-fn] afn (fn [vals structure next-fn]
(next-fn (conj vals (cfn this structure)) structure) (next-fn (conj vals (cfn this structure)) structure)
)] )]
(->StructureValsPathFunctions afn afn))) (->TransformFunctions StructureValsPathExecutor afn afn)))
(defn coerce-structure-path [this] (defn coerce-structure-path [this]
(let [pimpl (find-protocol-impl! StructurePath this) (let [pimpl (find-protocol-impl! StructurePath this)
selector (:select* pimpl) selector (:select* pimpl)
updater (:update* pimpl)] updater (:update* pimpl)]
(->StructureValsPathFunctions (->TransformFunctions
StructureValsPathExecutor
(fn [vals structure next-fn] (fn [vals structure next-fn]
(selector this structure (fn [structure] (next-fn vals structure)))) (selector this structure (fn [structure] (next-fn vals structure))))
(fn [vals structure next-fn] (fn [vals structure next-fn]
@ -69,9 +98,9 @@
(defn obj-extends? [prot obj] (defn obj-extends? [prot obj]
(->> obj (find-protocol-impl prot) nil? not)) (->> obj (find-protocol-impl prot) nil? not))
(extend-protocol CoerceStructureValsPathFunctions (extend-protocol CoerceTransformFunctions
StructureValsPathFunctions TransformFunctions
(coerce-path [this] (coerce-path [this]
this) this)
@ -94,12 +123,20 @@
(coerce-path sp)) (coerce-path sp))
java.util.List java.util.List
(comp-paths* [structure-paths] (comp-paths* [structure-paths]
(reduce (fn [^StructureValsPathFunctions sp-curr ^StructureValsPathFunctions sp] ;;TODO: need to get smart here
;; - select/update become stupid and just run execute-select / execute-update
;; - coerce-path doesn't go all the way to structurevalspath interface but actually keeps things as is
;; (except for collector)
;; - compose together consecutive structurepaths and consecutive structurevalspath
;; - if only one structurepath remaining, return that
;; - otherwise coerce structurepath to structurevalspath and finish combining
(reduce (fn [^TransformFunctions sp-curr ^TransformFunctions sp]
(let [curr-selector (.selector sp-curr) (let [curr-selector (.selector sp-curr)
selector (.selector sp) selector (.selector sp)
curr-updater (.updater sp-curr) curr-updater (.updater sp-curr)
updater (.updater sp)] updater (.updater sp)]
(->StructureValsPathFunctions (->TransformFunctions
StructureValsPathExecutor
(fn [vals structure next-fn] (fn [vals structure next-fn]
(curr-selector vals structure (curr-selector vals structure
(fn [vals-next structure-next] (fn [vals-next structure-next]
@ -296,7 +333,6 @@
(deftype KeyPath [akey]) (deftype KeyPath [akey])
(extend-protocol StructurePath (extend-protocol StructurePath
KeyPath KeyPath
(select* [^KeyPath this structure next-fn] (select* [^KeyPath this structure next-fn]