added richnav and fixed if-path with value collection

This commit is contained in:
Nathan Marz 2016-06-16 09:09:29 -04:00
parent bb058a24b9
commit 36f0e63d56
3 changed files with 120 additions and 28 deletions

View file

@ -8,6 +8,7 @@
defcollector
defnav
defpathedfn
richnav
]]
[com.rpl.specter.util-macros :refer
[doseqres]]
@ -19,7 +20,8 @@
fixed-pathed-nav
defcollector
defnav
defpathedfn]]
defpathedfn
richnav]]
#+clj [com.rpl.specter.util-macros :only [doseqres]]
)
(:require [com.rpl.specter.impl :as i]
@ -585,21 +587,67 @@
([cond-p then-path]
(if-path cond-p then-path STOP))
([cond-p then-path else-path]
(if-let [afn (i/extract-basic-filter-fn cond-p)]
(fixed-pathed-nav [late-then then-path
late-else else-path]
(select* [this structure next-fn]
(i/if-select structure next-fn afn late-then late-else))
(transform* [this structure next-fn]
(i/if-transform structure next-fn afn late-then late-else)))
(fixed-pathed-nav [late-cond cond-p
late-then then-path
late-else else-path]
(select* [this structure next-fn]
(i/if-select structure next-fn #(i/selected?* late-cond %) late-then late-else))
(transform* [this structure next-fn]
(i/if-transform structure next-fn #(i/selected?* late-cond %) late-then late-else))
))))
(let [then-comp (i/comp-paths* then-path)
else-comp (i/comp-paths* else-path)
then-needed (i/num-needed-params then-comp)
else-needed (i/num-needed-params else-comp)
[then-s then-t] (i/extract-rich-tfns then-comp)
[else-s else-t] (i/extract-rich-tfns else-comp)]
(if-let [afn (i/extract-basic-filter-fn cond-p)]
(richnav (+ then-needed else-needed)
(select* [params params-idx vals structure next-fn]
(i/if-select
params
params-idx
vals
structure
next-fn
afn
then-s
then-needed
else-s
))
(transform* [params params-idx vals structure next-fn]
(i/if-transform
params
params-idx
vals
structure
next-fn
afn
then-t
then-needed
else-t
))))
(let [cond-comp (i/comp-paths* cond-p)
cond-needed (i/num-needed-params cond-comp)]
(richnav (+ then-needed else-needed cond-needed)
(select* [params params-idx vals structure next-fn]
(let [late-cond (i/parameterize-path cond-comp params params-idx)]
(i/if-select
params
(+ params-idx cond-needed)
vals
structure
next-fn
#(i/selected?* late-cond %)
then-s
then-needed
else-s
)))
(transform* [params params-idx vals structure next-fn]
(let [late-cond (i/parameterize-path cond-comp params params-idx)]
(i/if-transform
params
(+ params-idx cond-needed)
vals
structure
next-fn
#(i/selected?* late-cond %)
then-t
then-needed
else-t
))))))))
(defpathedfn cond-path
"Takes in alternating cond-path path cond-path path...

View file

@ -417,7 +417,7 @@
(defn num-needed-params [path]
(if (instance? CompiledPath path)
0
(:num-needed-params path)))
(.-num-needed-params ^ParamsNeededPath path)))
;; cell implementation idea taken from prismatic schema library
@ -1075,18 +1075,33 @@
path
)))
(defn if-select [structure next-fn then-tester late-then late-else]
(let [apath (if (then-tester structure)
late-then
late-else)]
(compiled-traverse* apath next-fn structure)))
(defn if-transform [structure next-fn then-tester late-then late-else]
(let [apath (if (then-tester structure)
late-then
late-else)]
(compiled-transform* apath next-fn structure)
))
(defn if-select [params params-idx vals structure next-fn then-tester then-s then-params else-s]
(let [test? (then-tester structure)
sel (if test?
then-s
else-s)
idx (if test? params-idx (+ params-idx then-params))]
(sel params
idx
vals
structure
next-fn
)))
(defn if-transform [params params-idx vals structure next-fn then-tester then-t then-params else-t]
(let [test? (then-tester structure)
tran (if test?
then-t
else-t)
idx (if test? params-idx then-params)]
(tran params
idx
vals
structure
next-fn
)))
(defn filter-select [afn structure next-fn]
(if (afn structure)
@ -1480,3 +1495,15 @@
expected-params " but got " needed-params))
(extend atype protpath-prot {m (fn [_] rp)})
))))
(defn parameterize-path [apath params params-idx]
(if (instance? CompiledPath apath)
apath
(bind-params* apath params params-idx)
))
(defn extract-rich-tfns [apath]
(let [tfns (coerce-tfns-rich (:transform-fns apath))]
[(:selector tfns) (:transformer tfns)]
))

View file

@ -124,6 +124,23 @@
(paramsnav* retrieve-params num-params [impl1 impl2])
))
(defmacro richnav
"Defines a navigator with full access to collected vals, the parameters array,
and the parameters array index. `next-fn` expects to receive the params array,
the next params index, the collected vals, and finally the next structure.
This is the lowest level way of making navigators."
[num-params impl1 impl2]
(let [[select-impl transform-impl] (determine-params-impls impl1 impl2)]
`(let [tfns# (i/->TransformFunctions
i/RichPathExecutor
(fn ~@select-impl)
(fn ~@transform-impl)
)]
(if (zero? ~num-params)
(i/no-params-compiled-path tfns#)
(i/->ParamsNeededPath tfns# ~num-params)
))))
(defmacro paramsfn [params [structure-sym] & impl]
`(nav ~params
(~'select* [this# structure# next-fn#]