Add BEFORE-ELEM, AFTER-ELEM, and NONE-ELEM navigators
This commit is contained in:
parent
7c798c1e3b
commit
b79a71decd
5 changed files with 94 additions and 21 deletions
|
|
@ -7,6 +7,7 @@
|
|||
* `select-first` and `select-any` now avoid traversal beyond the first value matched by the path (like when using `ALL`), so they are faster now for those use cases.
|
||||
* Add `NAME` and `NAMESPACE` navigators
|
||||
* Extend `srange`, `BEGINNING`, `END`, `FIRST`, and `LAST` on strings to navigate to substrings
|
||||
* Add `BEFORE-ELEM`, `AFTER-ELEM`, and `NONE-ELEM` for efficiently adding a single element to a sequence or set
|
||||
* Improved `ALL` performance for PersistentHashSet
|
||||
* Dynamic navs automatically compile sequence returns if completely static
|
||||
* Eliminate reflection warnings for clj (thanks @mpenet)
|
||||
|
|
|
|||
|
|
@ -199,9 +199,10 @@
|
|||
|
||||
|
||||
(let [v (vec (range 1000))]
|
||||
(run-benchmark "END on large vector"
|
||||
(run-benchmark "Append to a large vector"
|
||||
2000000
|
||||
(setval END [1] v)
|
||||
(setval AFTER-ELEM 1 v)
|
||||
(reduce conj v [1])
|
||||
(conj v 1)))
|
||||
|
||||
|
|
|
|||
|
|
@ -726,6 +726,51 @@
|
|||
(let [to-append (next-fn [])]
|
||||
(n/append-all structure to-append)))))
|
||||
|
||||
(defnav
|
||||
^{:doc "Navigate to 'void' elem in the set.
|
||||
For transformations - if result is not `NONE`,
|
||||
then add that value to the set."}
|
||||
NONE-ELEM
|
||||
[]
|
||||
(select* [this structure next-fn]
|
||||
(next-fn NONE))
|
||||
(transform* [this structure next-fn]
|
||||
(let [newe (next-fn NONE)]
|
||||
(if (identical? NONE newe)
|
||||
structure
|
||||
(conj structure newe)
|
||||
))))
|
||||
|
||||
(defnav
|
||||
^{:doc "Navigate to 'void' element before the sequence.
|
||||
For transformations – if result is not `NONE`,
|
||||
then prepend that value."}
|
||||
BEFORE-ELEM
|
||||
[]
|
||||
(select* [this structure next-fn]
|
||||
(next-fn NONE))
|
||||
(transform* [this structure next-fn]
|
||||
(let [newe (next-fn NONE)]
|
||||
(if (identical? NONE newe)
|
||||
structure
|
||||
(n/prepend-one structure newe)
|
||||
))))
|
||||
|
||||
(defnav
|
||||
^{:doc "Navigate to 'void' element after the sequence.
|
||||
For transformations – if result is not `NONE`,
|
||||
then append that value."}
|
||||
AFTER-ELEM
|
||||
[]
|
||||
(select* [this structure next-fn]
|
||||
(next-fn NONE))
|
||||
(transform* [this structure next-fn]
|
||||
(let [newe (next-fn NONE)]
|
||||
(if (identical? NONE newe)
|
||||
structure
|
||||
(n/append-one structure newe)
|
||||
))))
|
||||
|
||||
(defnav
|
||||
^{:doc "Navigates to the specified subset (by taking an intersection).
|
||||
In a transform, that subset in the original set is changed to the
|
||||
|
|
|
|||
|
|
@ -344,7 +344,10 @@
|
|||
|
||||
(defprotocol AddExtremes
|
||||
(append-all [structure elements])
|
||||
(prepend-all [structure elements]))
|
||||
(prepend-all [structure elements])
|
||||
(append-one [structure elem])
|
||||
(prepend-one [structure elem])
|
||||
)
|
||||
|
||||
(extend-protocol AddExtremes
|
||||
nil
|
||||
|
|
@ -352,6 +355,10 @@
|
|||
elements)
|
||||
(prepend-all [_ elements]
|
||||
elements)
|
||||
(append-one [_ elem]
|
||||
(list elem))
|
||||
(prepend-one [_ elem]
|
||||
(list elem))
|
||||
|
||||
#?(:clj clojure.lang.PersistentVector :cljs cljs.core/PersistentVector)
|
||||
(append-all [structure elements]
|
||||
|
|
@ -362,13 +369,22 @@
|
|||
(reduce conj! <> elements)
|
||||
(reduce conj! <> structure)
|
||||
(persistent! <>))))
|
||||
(append-one [structure elem]
|
||||
(conj structure elem))
|
||||
(prepend-one [structure elem]
|
||||
(into [elem] structure))
|
||||
|
||||
|
||||
#?(:clj Object :cljs default)
|
||||
(append-all [structure elements]
|
||||
(concat structure elements))
|
||||
(prepend-all [structure elements]
|
||||
(concat elements structure)))
|
||||
(concat elements structure))
|
||||
(append-one [structure elem]
|
||||
(concat structure [elem]))
|
||||
(prepend-one [structure elem]
|
||||
(cons elem structure))
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1410,25 +1410,35 @@
|
|||
)
|
||||
|
||||
(deftest name-namespace-test
|
||||
(= :a (setval s/NAME "a" :e))
|
||||
(= :a/b (setval s/NAME "b" :a/e))
|
||||
(= 'a (setval s/NAME "a" 'e))
|
||||
(= 'a/b (setval s/NAME "b" 'a/e))
|
||||
(= :a/e (setval s/NAMESPACE "a" :e))
|
||||
(= :a/e (setval s/NAMESPACE "a" :f/e))
|
||||
(= 'a/e (setval s/NAMESPACE "a" 'e))
|
||||
(= 'a/e (setval s/NAMESPACE "a" 'f/e))
|
||||
(is (= :a (setval s/NAME "a" :e)))
|
||||
(is (= :a/b (setval s/NAME "b" :a/e)))
|
||||
(is (= 'a (setval s/NAME "a" 'e)))
|
||||
(is (= 'a/b (setval s/NAME "b" 'a/e)))
|
||||
(is (= :a/e (setval s/NAMESPACE "a" :e)))
|
||||
(is (= :a/e (setval s/NAMESPACE "a" :f/e)))
|
||||
(is (= 'a/e (setval s/NAMESPACE "a" 'e)))
|
||||
(is (= 'a/e (setval s/NAMESPACE "a" 'f/e)))
|
||||
)
|
||||
|
||||
(deftest string-navigation-test
|
||||
(= "ad" (setval (s/srange 1 4) "" "abcd"))
|
||||
(= "bc" (select-any (s/srange 1 4) "abcd"))
|
||||
(= "ab" (setval s/END "b" "a"))
|
||||
(= "ba" (setval s/BEGINNING "b" "a"))
|
||||
(= "" (select-any s/BEGINNING "abc"))
|
||||
(= "" (select-any s/END "abc"))
|
||||
(= \a (select-any s/FIRST "abc"))
|
||||
(= \c (select-any s/LAST "abc"))
|
||||
(= "qbc" (setval s/FIRST \q "abc"))
|
||||
(= "abq" (setval s/FIRST "q" "abc"))
|
||||
(is (= "ad" (setval (s/srange 1 3) "" "abcd")))
|
||||
(is (= "bc" (select-any (s/srange 1 3) "abcd")))
|
||||
(is (= "ab" (setval s/END "b" "a")))
|
||||
(is (= "ba" (setval s/BEGINNING "b" "a")))
|
||||
(is (= "" (select-any s/BEGINNING "abc")))
|
||||
(is (= "" (select-any s/END "abc")))
|
||||
(is (= \a (select-any s/FIRST "abc")))
|
||||
(is (= \c (select-any s/LAST "abc")))
|
||||
(is (= "qbc" (setval s/FIRST \q "abc")))
|
||||
(is (= "abq" (setval s/LAST "q" "abc")))
|
||||
)
|
||||
|
||||
(deftest single-value-none-navigators-test
|
||||
(is (predand= vector? [1 2 3] (setval s/AFTER-ELEM 3 [1 2])))
|
||||
(is (predand= list? '(1 2 3) (setval s/AFTER-ELEM 3 '(1 2))))
|
||||
(is (predand= list? '(1) (setval s/AFTER-ELEM 1 nil)))
|
||||
(is (predand= vector? [3 1 2] (setval s/BEFORE-ELEM 3 [1 2])))
|
||||
(is (predand= list? '(3 1 2) (setval s/BEFORE-ELEM 3 '(1 2))))
|
||||
(is (predand= list? '(1) (setval s/BEFORE-ELEM 1 nil)))
|
||||
(is (= #{1 2 3} (setval s/NONE-ELEM 3 #{1 2})))
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in a new issue