broken implementation of skipping protocols
This commit is contained in:
parent
277735dd9b
commit
47aee4d000
4 changed files with 69 additions and 28 deletions
|
|
@ -4,6 +4,7 @@
|
|||
:jvm-opts ["-XX:-OmitStackTraceInFastThrow"] ; this prevents JVM from doing optimizations which can remove stack traces from NPE and other exceptions
|
||||
:source-paths ["src/clj"]
|
||||
:test-paths ["test/clj"]
|
||||
:plugins [[lein-nodisassemble "0.1.3"]]
|
||||
:profiles {:dev {:dependencies
|
||||
[[org.clojure/test.check "0.5.9"]]}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -22,6 +22,13 @@
|
|||
(if-not (empty? vals) [(conj vals structure)] [structure])))
|
||||
))
|
||||
|
||||
(defn select-fast
|
||||
[^com.rpl.specter.impl.StructureValsPathFunctions selfns structure]
|
||||
((.selector selfns) [] structure
|
||||
(fn [vals structure]
|
||||
(if-not (empty? vals) [(conj vals structure)] [structure])))
|
||||
)
|
||||
|
||||
(defn select-one
|
||||
"Like select, but returns either one element or nil. Throws exception if multiple elements found"
|
||||
[selector structure]
|
||||
|
|
@ -67,7 +74,7 @@
|
|||
|
||||
(defn replace-in [selector update-fn structure & {:keys [merge-fn] :or {merge-fn concat}}]
|
||||
"Similar to update, except returns a pair of [updated-structure sequence-of-user-ret].
|
||||
The update-fn in this case is expected to return [ret user-ret]. ret is
|
||||
The update-fn in this case is expected to return [ret user-ret]. ret is
|
||||
what's used to update the data structure, while user-ret will be added to the user-ret sequence
|
||||
in the final return. replace-in is useful for situations where you need to know the specific values
|
||||
of what was updated in the data structure."
|
||||
|
|
|
|||
|
|
@ -9,31 +9,55 @@
|
|||
(dotimes [_ iters]
|
||||
(afn))))
|
||||
|
||||
(defprotocol CoerceStructureValsPath
|
||||
(deftype StructureValsPathFunctions [selector updater]
|
||||
StructureValsPath
|
||||
(select-full* [this vals structure next-fn]
|
||||
(selector vals structure next-fn))
|
||||
(update-full* [this vals structure next-fn]
|
||||
(updater vals structure next-fn)))
|
||||
|
||||
(defprotocol CoerceStructureValsPathFunctions
|
||||
(coerce-path [this]))
|
||||
|
||||
(extend-protocol CoerceStructureValsPath
|
||||
(extend-protocol CoerceStructureValsPathFunctions
|
||||
|
||||
com.rpl.specter.protocols.StructureValsPath
|
||||
(coerce-path [this] this)
|
||||
(coerce-path [this]
|
||||
(let [pimpl (->> this
|
||||
(find-protocol-impl StructureValsPath))
|
||||
selector (:select-full* pimpl)
|
||||
updater (:update-full* pimpl)]
|
||||
(->StructureValsPathFunctions
|
||||
(fn [vals structure next-fn]
|
||||
(selector this vals structure next-fn))
|
||||
(fn [vals structure next-fn]
|
||||
(updater this vals structure next-fn)))
|
||||
))
|
||||
|
||||
com.rpl.specter.protocols.Collector
|
||||
(coerce-path [collector]
|
||||
(reify StructureValsPath
|
||||
(select-full* [this vals structure next-fn]
|
||||
(next-fn (conj vals (collect-val collector structure)) structure))
|
||||
(update-full* [this vals structure next-fn]
|
||||
(next-fn (conj vals (collect-val collector structure)) structure))))
|
||||
(let [pimpl (->> collector
|
||||
(find-protocol-impl Collector)
|
||||
:collect-val
|
||||
)
|
||||
afn (fn [vals structure next-fn]
|
||||
(next-fn (conj vals (pimpl collector structure)) structure)
|
||||
)]
|
||||
(->StructureValsPathFunctions afn afn)))
|
||||
|
||||
;; need to say Object instead of StructurePath so that things like Keyword are properly coerced
|
||||
Object
|
||||
(coerce-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)))
|
||||
)))
|
||||
(coerce-path [this]
|
||||
(let [pimpl (->> this
|
||||
(find-protocol-impl StructurePath))
|
||||
selector (:select* pimpl)
|
||||
updater (:update* pimpl)]
|
||||
(->StructureValsPathFunctions
|
||||
(fn [vals structure next-fn]
|
||||
(selector this structure (fn [structure] (next-fn vals structure))))
|
||||
(fn [vals structure next-fn]
|
||||
(updater this structure (fn [structure] (next-fn vals structure))))
|
||||
)))
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -43,18 +67,26 @@
|
|||
(coerce-path sp))
|
||||
java.util.List
|
||||
(comp-paths* [structure-paths]
|
||||
(reduce (fn [sp-curr sp]
|
||||
(reify StructureValsPath
|
||||
(select-full* [this vals structure next-fn]
|
||||
(select-full* sp vals structure
|
||||
(fn [vals-next structure-next]
|
||||
(select-full* sp-curr vals-next structure-next next-fn)))
|
||||
)
|
||||
(update-full* [this vals structure next-fn]
|
||||
(update-full* sp vals structure
|
||||
(fn [vals-next structure-next]
|
||||
(update-full* sp-curr vals-next structure-next next-fn))))
|
||||
))
|
||||
;;TODO: don't reify any protocols... instead coerce to a "StructureValsPathFunctions" record
|
||||
;; and compose functions directly
|
||||
|
||||
(reduce (fn [^StructureValsPathFunctions sp-curr ^StructureValsPathFunctions sp]
|
||||
(let [curr-selector (.selector sp-curr)
|
||||
selector (.selector sp)
|
||||
curr-updater (.updater sp-curr)
|
||||
updater (.updater sp)]
|
||||
(->StructureValsPathFunctions
|
||||
(fn [vals structure next-fn]
|
||||
(selector vals structure
|
||||
(fn [vals-next structure-next]
|
||||
(curr-selector vals-next structure-next next-fn)
|
||||
)))
|
||||
(fn [vals structure next-fn]
|
||||
(updater vals structure
|
||||
(fn [vals-next structure-next]
|
||||
(curr-updater vals-next structure-next next-fn)
|
||||
)))
|
||||
)))
|
||||
(->> structure-paths flatten (map coerce-path) reverse))
|
||||
))
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
(ns com.rpl.specter.protocols)
|
||||
|
||||
|
||||
;;TODO: can use find-protocol-impl function to avoid all the protocol calls
|
||||
(defprotocol StructureValsPath
|
||||
(select-full* [this vals structure next-fn])
|
||||
(update-full* [this vals structure next-fn]))
|
||||
|
|
|
|||
Loading…
Reference in a new issue