From ffd6464d54a71d3ce2e7a4e22453fd6bffc819be Mon Sep 17 00:00:00 2001 From: Nathan Marz Date: Tue, 14 Apr 2015 23:49:32 -0400 Subject: [PATCH] added srange, srange-dyamic, START, and END dynamic paths to manipulate parts of a sequence by index --- src/clj/com/rpl/specter.clj | 8 ++++++++ src/clj/com/rpl/specter/impl.clj | 21 +++++++++++++++++++++ test/clj/com/rpl/specter/core_test.clj | 26 ++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/src/clj/com/rpl/specter.clj b/src/clj/com/rpl/specter.clj index ab4291b..a303c0e 100644 --- a/src/clj/com/rpl/specter.clj +++ b/src/clj/com/rpl/specter.clj @@ -86,6 +86,14 @@ (def FIRST (->FirstStructurePath)) +(defn srange-dynamic [start-fn end-fn] (->SRangePath start-fn end-fn)) + +(defn srange [start end] (srange-dynamic (fn [_] start) (fn [_] end))) + +(def START (srange 0 0)) + +(def END (srange-dynamic count count)) + (defn walker [afn] (->WalkerStructurePath afn)) (defn codewalker [afn] (->CodeWalkerStructurePath afn)) diff --git a/src/clj/com/rpl/specter/impl.clj b/src/clj/com/rpl/specter/impl.clj index 62d649b..3880901 100644 --- a/src/clj/com/rpl/specter/impl.clj +++ b/src/clj/com/rpl/specter/impl.clj @@ -145,6 +145,7 @@ (let [empty-structure (empty structure) pfn (partial next-fn vals)] (if (list? empty-structure) + ;; this is done to maintain order, otherwise lists get reversed (doall (map pfn structure)) (->> structure (r/map pfn) (into empty-structure)) )))) @@ -217,3 +218,23 @@ (selector-vals* sel-fn selector vals structure next-fn)) (update* [this vals structure next-fn] (selector-vals* sel-fn selector vals structure next-fn))) + +(deftype SRangePath [start-fn end-fn] + StructurePath + (select* [this vals structure next-fn] + (let [start (start-fn structure) + end (end-fn structure)] + (next-fn vals (-> structure vec (subvec start end))) + )) + (update* [this vals structure next-fn] + (let [start (start-fn structure) + end (end-fn structure) + structurev (vec structure) + newpart (next-fn vals (-> structurev (subvec start end))) + res (concat (subvec structurev 0 start) + newpart + (subvec structurev end (count structure)))] + (if (vector? structure) + (vec res) + res + )))) diff --git a/test/clj/com/rpl/specter/core_test.clj b/test/clj/com/rpl/specter/core_test.clj index f2e67a3..a3cc319 100644 --- a/test/clj/com/rpl/specter/core_test.clj +++ b/test/clj/com/rpl/specter/core_test.clj @@ -180,6 +180,32 @@ [res user-ret] )))) +(defspec srange-extremes-test + (for-all+ + [v (gen/vector gen/int) + v2 (gen/vector gen/int)] + (let [b (setval START v2 v) + e (setval END v2 v)] + (and (= b (concat v2 v)) + (= e (concat v v2))) + ))) + +(defspec srange-test + (for-all+ + [v (gen/vector gen/int) + b (gen/elements (-> v count inc range)) + e (gen/elements (range b (-> v count inc))) + ] + (let [sv (subvec v b e) + predcount (fn [pred v] (->> v (filter pred) count)) + even-count (partial predcount even?) + odd-count (partial predcount odd?) + b (update (srange b e) (fn [r] (filter odd? r)) v)] + (and (= (odd-count v) (odd-count b)) + (= (+ (even-count b) (even-count sv)) + (even-count v))) + ))) + (deftest structure-path-directly-test (is (= 3 (select-one :b {:a 1 :b 3}))) (is (= 5 (select-one (comp-structure-paths :a :b) {:a {:b 5}})))