Add nthpath navigator

This commit is contained in:
nathanmarz 2017-02-12 21:13:08 -05:00
parent ebdfc80d8b
commit 646e03a227
4 changed files with 39 additions and 4 deletions

View file

@ -1,12 +1,13 @@
## 0.13.3-SNAPSHOT
* Transform to `com.rpl.specter/NONE` to remove elements from data structures. Works with `keypath` (for both sequences and maps), `must`, `ALL`, and `MAP-VALS`
* Dynamic navs automatically compile sequence returns if completely static
* Eliminate reflection warnings for clj (thanks @mpenet)
* Add `nthpath` navigator
* Add `with-fresh-collected` higher order navigator
* Added `traverse-all` which returns a transducer that traverses over all elements matching the given path.
* `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.
* Improved `ALL` performance for PersistentHashSet
* Dynamic navs automatically compile sequence returns if completely static
* Eliminate reflection warnings for clj (thanks @mpenet)
## 0.13.2

View file

@ -796,6 +796,7 @@
(def keypath (eachnav n/keypath*))
(def must (eachnav n/must*))
(def nthpath (eachnav n/nthpath*))
(defrichnav

View file

@ -481,7 +481,8 @@
(assoc structure key newv))))
(defrichnav
^{:doc "Navigates to the specified key, navigating to nil if it does not exist."}
^{:doc "Navigates to the specified key, navigating to nil if it does not exist.
Setting the value to NONE will remove it from the collection."}
keypath*
[key]
(select* [this vals structure next-fn]
@ -492,7 +493,8 @@
(defrichnav
^{:doc "Navigates to the key only if it exists in the map."}
^{:doc "Navigates to the key only if it exists in the map. Setting the value to NONE
will remove it from the collection."}
must*
[k]
(select* [this vals structure next-fn]
@ -503,3 +505,26 @@
(if (contains? structure k)
(do-keypath-transform vals structure k next-fn)
structure)))
(defnav nthpath*
^{:doc "Navigates to the given position in the sequence. Setting the value to NONE
will remove it from the sequence. Works for all sequence types."}
[i]
(select* [this structure next-fn]
(next-fn (nth structure i)))
(transform* [this structure next-fn]
(if (vector? structure)
(let [newv (next-fn (nth structure i))]
(if (identical? newv i/NONE)
(i/srange-transform* structure i (inc i) (fn [_] []))
(assoc structure i newv)))
(i/srange-transform* ; can make this much more efficient with alternate impl
structure
i
(inc i)
(fn [[e]]
(let [v (next-fn e)]
(if (identical? v i/NONE)
[]
[v])
))))))

View file

@ -1322,6 +1322,14 @@
(and (pred ret)
(= ret v)))
(deftest nthpath-test
(is (predand= vector? [1 2 -3 4] (transform (s/nthpath 2) - [1 2 3 4])))
(is (predand= vector? [1 2 4] (setval (s/nthpath 2) s/NONE [1 2 3 4])))
(is (predand= (complement vector?) '(1 -2 3 4) (transform (s/nthpath 1) - '(1 2 3 4))))
(is (predand= (complement vector?) '(1 2 4) (setval (s/nthpath 2) s/NONE '(1 2 3 4))))
(is (= [0 1 [2 4 4]] (transform (s/nthpath 2 1) inc [0 1 [2 3 4]])))
)
(deftest remove-with-NONE-test
(is (predand= vector? [1 2 3] (setval [s/ALL nil?] s/NONE [1 2 nil 3 nil])))
(is (predand= list? '(1 2 3) (setval [s/ALL nil?] s/NONE '(1 2 nil 3 nil))))