add remove with NONE functionality to FIRST and LAST

This commit is contained in:
nathanmarz 2017-03-01 10:40:17 -05:00
parent 5e56a99163
commit b13b8d3c35
3 changed files with 82 additions and 13 deletions

View file

@ -1,6 +1,6 @@
## 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`
* Transform to `com.rpl.specter/NONE` to remove elements from data structures. Works with `keypath` (for both sequences and maps), `must`, `nthpath`, `ALL`, `MAP-VALS`, `FIRST`, and `LAST`
* 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.

View file

@ -476,10 +476,18 @@
(updater structure next-fn))))
(defn- update-first-list [l afn]
(cons (afn (first l)) (rest l)))
(let [newf (afn (first l))
restl (rest l)]
(if (identical? i/NONE newf)
restl
(cons newf restl))))
(defn- update-last-list [l afn]
(concat (butlast l) [(afn (last l))]))
(let [lastl (afn (last l))
bl (butlast l)]
(if (identical? i/NONE lastl)
(if (nil? bl) '() bl)
(concat bl [lastl]))))
#?(
:clj
@ -504,26 +512,49 @@
(extend-protocol UpdateExtremes
#?(:clj clojure.lang.IPersistentVector :cljs cljs.core/PersistentVector)
(update-first [v afn]
(let [val (nth v 0)]
(assoc v 0 (afn val))))
(let [val (nth v 0)
newv (afn val)]
(if (identical? i/NONE newv)
(subvec v 1)
(assoc v 0 newv)
)))
(update-last [v afn]
;; type-hinting vec-count to ^int caused weird errors with case
(let [c (int (vec-count v))]
(case c
1 (let [[e] v] [(afn e)])
2 (let [[e1 e2] v] [e1 (afn e2)])
(let [i (dec c)]
(assoc v i (afn (nth v i)))))))
1 (let [[e] v
newe (afn e)]
(if (identical? i/NONE newe)
[]
[newe]))
2 (let [[e1 e2] v
newe (afn e2)]
(if (identical? i/NONE newe)
[e1]
[e1 newe]))
(let [i (dec c)
newe (afn (nth v i))]
(if (identical? i/NONE newe)
(pop v)
(assoc v i newe))))))
#?(:clj String :cljs string)
(update-first [s afn]
(str (afn (nth s 0)) (subs s 1 (count s))))
(let [rests (subs s 1 (count s))
newb (afn (nth s 0))]
(if (identical? i/NONE newb)
rests
(str newb rests))))
(update-last [s afn]
(let [last-idx (-> s count dec)]
(str (subs s 0 last-idx) (afn (nth s last-idx)))
))
(let [last-idx (-> s count dec)
newl (afn (nth s last-idx))
begins (subs s 0 last-idx)]
(if (identical? i/NONE newl)
begins
(str begins newl)
)))
#?(:clj Object :cljs default)
(update-first [l val]

View file

@ -1469,3 +1469,41 @@
(= (select s/MAP-KEYS m)
(select [s/ALL s/FIRST] m)
)))
(defspec remove-first-vector
(for-all+
[v (limit-size 10 (gen/not-empty (gen/vector gen/int)))]
(let [newv (setval s/FIRST s/NONE v)]
(and (= newv (vec (rest v)))
(vector? newv)
))))
(defspec remove-first-list
(for-all+
[l (limit-size 10 (gen/not-empty (gen/list gen/int)))]
(let [newl (setval s/FIRST s/NONE l)]
(and (= newl (rest l))
(list? newl)
))))
(defspec remove-last-vector
(for-all+
[v (limit-size 10 (gen/not-empty (gen/vector gen/int)))]
(let [newv (setval s/LAST s/NONE v)]
(and (= newv (vec (butlast v)))
(vector? newv)
))))
(defspec remove-last-list
(for-all+
[l (limit-size 10 (gen/not-empty (gen/list gen/int)))]
(let [newl (setval s/LAST s/NONE l)
bl (butlast l)]
(and (or (= newl bl) (and (nil? bl) (= '() newl)))
(seq? newl)
))))
(deftest remove-extreme-string
(is (= "b" (setval s/FIRST s/NONE "ab")))
(is (= "a" (setval s/LAST s/NONE "ab")))
)