add ability to declare end-fn for srange-dynamic that takes in result of start-fn

This commit is contained in:
nathanmarz 2017-06-07 17:14:20 -04:00
parent 8f30918d59
commit 3e4730b44f
4 changed files with 38 additions and 5 deletions

View file

@ -7,6 +7,7 @@
* `walker` and `codewalker` can now be used with `NONE` to remove elements
* Improve `walker` performance by 70% by replacing clojure.walk implementation with custom recursive path
* Extend `ALL` to work on records (navigate to key/value pairs)
* Add ability to declare a function for end index of `srange-dynamic` that takes in the result of the start index fn. Use `end-fn` macro to declare this function (takes in 2 args of [collection, start-index]). Functions defined with normal mechanisms (e.g. `fn`) will still only take in the collection as an argument.
* Workaround ClojureScript bug that emits warnings for vars named the same as a private var in cljs.core (in this case `NONE`, added as private var to cljs.core with 1.9.562)
* For ALL transforms on maps, interpret transformed key/value pair of size < 2 as removal
* Bug fix: Fix incorrect inline compilation when a dynamic function invocation is nested in a data structure within a parameter to a navigator builder

View file

@ -452,7 +452,12 @@
embed (vec (for [[t p] extensions] [t `(quote ~p)]))]
`(extend-protocolpath*
~(protpath-sym protpath)
~embed)))))
~embed)))
(defmacro end-fn [& args]
`(n/->SrangeEndFunction (fn ~@args)))
))
@ -710,9 +715,11 @@
srange-dynamic
[start-fn end-fn]
(select* [this structure next-fn]
(n/srange-select structure (start-fn structure) (end-fn structure) next-fn))
(let [s (start-fn structure)]
(n/srange-select structure s (n/invoke-end-fn end-fn structure s) next-fn)))
(transform* [this structure next-fn]
(n/srange-transform structure (start-fn structure) (end-fn structure) next-fn)))
(let [s (start-fn structure)]
(n/srange-transform structure s (n/invoke-end-fn end-fn structure s) next-fn))))
(defnav

View file

@ -659,3 +659,12 @@
[]
[v])
))))))
(defrecord SrangeEndFunction [end-fn])
;; done this way to maintain backwards compatibility
(defn invoke-end-fn [end-fn structure start]
(if (instance? SrangeEndFunction end-fn)
((:end-fn end-fn) structure start)
(end-fn structure)
))

View file

@ -10,7 +10,7 @@
select-first transform setval replace-in
select-any selected-any? collected? traverse
multi-transform path dynamicnav recursive-path
defdynamicnav traverse-all satisfies-protpath?]]))
defdynamicnav traverse-all satisfies-protpath? end-fn]]))
(:use
#?(:clj [clojure.test :only [deftest is]])
#?(:clj [clojure.test.check.clojure-test :only [defspec]])
@ -21,7 +21,7 @@
select-first transform setval replace-in
select-any selected-any? collected? traverse
multi-transform path dynamicnav recursive-path
defdynamicnav traverse-all satisfies-protpath?]]))
defdynamicnav traverse-all satisfies-protpath? end-fn]]))
@ -1561,6 +1561,22 @@
(is (= (assoc f :b 1 :c 2) (transform [(s/walker (complement record?)) s/FIRST] (fn [k] (if (= :a k) :b :c)) f)))
))
(def MIDDLE
(s/comp-paths
(s/srange-dynamic
(fn [aseq] (long (/ (count aseq) 2)))
(end-fn [aseq s] (if (empty? aseq) 0 (inc s))))
s/FIRST
))
(deftest srange-dynamic-test
(is (= 2 (select-any MIDDLE [1 2 3])))
(is (identical? s/NONE (select-any MIDDLE [])))
(is (= 1 (select-any MIDDLE [1])))
(is (= 2 (select-any MIDDLE [1 2])))
(is (= [1 3 3] (transform MIDDLE inc [1 2 3])))
)
#?(:clj
(do
(defprotocolpath FooPP)