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

View file

@ -15,9 +15,36 @@
(dotimes [_ iters]
(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]))
(defn no-prot-error-str [obj]
@ -38,7 +65,8 @@
(let [pimpl (find-protocol-impl! StructureValsPath this)
selector (:select-full* pimpl)
updater (:update-full* pimpl)]
(->StructureValsPathFunctions
(->TransformFunctions
StructureValsPathExecutor
(fn [vals structure next-fn]
(selector this vals structure next-fn))
(fn [vals structure next-fn]
@ -53,13 +81,14 @@
afn (fn [vals structure next-fn]
(next-fn (conj vals (cfn this structure)) structure)
)]
(->StructureValsPathFunctions afn afn)))
(->TransformFunctions StructureValsPathExecutor afn afn)))
(defn coerce-structure-path [this]
(let [pimpl (find-protocol-impl! StructurePath this)
selector (:select* pimpl)
updater (:update* pimpl)]
(->StructureValsPathFunctions
(->TransformFunctions
StructureValsPathExecutor
(fn [vals structure next-fn]
(selector this structure (fn [structure] (next-fn vals structure))))
(fn [vals structure next-fn]
@ -69,9 +98,9 @@
(defn obj-extends? [prot obj]
(->> obj (find-protocol-impl prot) nil? not))
(extend-protocol CoerceStructureValsPathFunctions
(extend-protocol CoerceTransformFunctions
StructureValsPathFunctions
TransformFunctions
(coerce-path [this]
this)
@ -94,12 +123,20 @@
(coerce-path sp))
java.util.List
(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)
selector (.selector sp)
curr-updater (.updater sp-curr)
updater (.updater sp)]
(->StructureValsPathFunctions
(->TransformFunctions
StructureValsPathExecutor
(fn [vals structure next-fn]
(curr-selector vals structure
(fn [vals-next structure-next]
@ -295,7 +332,6 @@
ancestry))))
(deftype KeyPath [akey])
(extend-protocol StructurePath
KeyPath