implemented declarepath/providepath

This commit is contained in:
Nathan Marz 2016-01-14 17:36:49 -05:00
parent 1905157c3c
commit dd6dafc390
4 changed files with 67 additions and 10 deletions

View file

@ -6,6 +6,7 @@
* Fix replace-in to work with value collection
* Added STAY selector
* Added stay-then-continue and continue-then-stay selectors which enable pre-order/post-order traversals
* Added declarepath and providepath, which enable arbitrary recursive or mutually recursive paths
## 0.9.1
* Fixed reflection in protocol path code

View file

@ -7,8 +7,6 @@
fixed-pathed-path
defcollector
defpath
paramscollector
paramspath
]]
)
(:use [com.rpl.specter.protocols :only [StructurePath]]
@ -17,9 +15,7 @@
variable-pathed-path
fixed-pathed-path
defcollector
defpath
paramscollector
paramspath]]
defpath]]
)
(:require [com.rpl.specter.impl :as i]
[clojure.set :as set])

View file

@ -108,7 +108,7 @@
(apply concat)))
(defmacro paramspath
(defmacro path
"Defines a StructurePath with late bound parameters. This path can be precompiled
with other selectors without knowing the parameters. When precompiled with other
selectors, the resulting selector takes in parameters for all selectors in the path
@ -120,7 +120,7 @@
))
(defmacro paramsfn [params [structure-sym] & impl]
`(paramspath ~params
`(path ~params
(~'select* [this# structure# next-fn#]
(let [afn# (fn [~structure-sym] ~@impl)]
(filter-select afn# structure# next-fn#)
@ -143,7 +143,7 @@
))
(defmacro defpath [name & body]
`(def ~name (paramspath ~@body)))
`(def ~name (path ~@body)))
(defmacro defcollector [name & body]
`(def ~name (paramscollector ~@body)))
@ -247,5 +247,39 @@
)
)))))
(defn declared-name [name]
(symbol (str name "-declared")))
(defmacro declarepath [name]
(let [declared (declared-name name)
rargs [(gensym "params") (gensym "pidx") (gensym "vals")
(gensym "structure") (gensym "next-fn")]]
`(do
(declare ~declared)
(def ~name
(no-params-compiled-path
(->TransformFunctions
RichPathExecutor
(fn ~rargs
(let [selector# (compiled-selector ~declared)]
(selector# ~@rargs)
))
(fn ~rargs
(let [transformer# (compiled-transformer ~declared)]
(transformer# ~@rargs)
))))
))))
(defmacro providepath [name apath]
`(def ~(declared-name name)
(update-in (comp-paths* ~apath)
[:transform-fns]
coerce-tfns-rich)
))
;;TODO: hmm... not sure how to proxy it as don't know if its paramsneeded/compiler or rich/regular
;;could require later definition to be done with "defproxiedpath" or wrapped in proxied-path
(defmacro extend-protocolpath [protpath & extensions]
`(extend-protocolpath* ~protpath ~(protpath-sym protpath) ~(vec extensions)))

View file

@ -3,12 +3,16 @@
[cljs.test :refer [is deftest]]
[cljs.test.check.cljs-test :refer [defspec]]
[com.rpl.specter.cljs-test-helpers :refer [for-all+]]
[com.rpl.specter.macros :refer [paramsfn defprotocolpath defpath extend-protocolpath]])
[com.rpl.specter.macros
:refer [paramsfn defprotocolpath defpath extend-protocolpath
declarepath providepath]])
(:use
#+clj [clojure.test :only [deftest is]]
#+clj [clojure.test.check.clojure-test :only [defspec]]
#+clj [com.rpl.specter.test-helpers :only [for-all+]]
#+clj [com.rpl.specter.macros :only [paramsfn defprotocolpath defpath extend-protocolpath]]
#+clj [com.rpl.specter.macros
:only [paramsfn defprotocolpath defpath extend-protocolpath
declarepath providepath]]
)
@ -589,6 +593,28 @@
(s/select (s/continue-then-stay s/ALL odd?) [1 2 3])))
)
(declarepath MyWalker)
(providepath MyWalker
(s/if-path vector?
(s/if-path [s/FIRST #(= :abc %)]
(s/continue-then-stay s/ALL MyWalker)
[s/ALL MyWalker]
)))
(deftest recursive-path-test
(is (= [9 1 10 3 1]
(s/select [MyWalker s/ALL number?]
[:bb [:aa 34 [:abc 10 [:ccc 9 8 [:abc 9 1]]]] [:abc 1 [:abc 3]]])
))
(is (= [:bb [:aa 34 [:abc 11 [:ccc 9 8 [:abc 10 2]]]] [:abc 2 [:abc 4]]]
(s/transform [MyWalker s/ALL number?] inc
[:bb [:aa 34 [:abc 10 [:ccc 9 8 [:abc 9 1]]]] [:abc 1 [:abc 3]]])
))
)
#+clj
(deftest large-params-test
(let [path (apply s/comp-paths (repeat 25 s/keypath))