From 5e51ef159d74ba81a177e3b5915430a47b95b9cd Mon Sep 17 00:00:00 2001 From: Jeff Evans Date: Mon, 3 Aug 2020 13:19:09 -0500 Subject: [PATCH] #223 - Improve before-index performance Adding before-index implementation that uses take/drop instead of setval/srange Adding new functional test to confirm behavior when operating on a string Adding benchmark for old versus new implementation of before-index --- scripts/benchmarks.clj | 6 ++++++ src/clj/com/rpl/specter.cljc | 24 +++++++++++++++++++++++- test/com/rpl/specter/core_test.cljc | 4 +++- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/scripts/benchmarks.clj b/scripts/benchmarks.clj index 84bc1be..5cdd7f9 100644 --- a/scripts/benchmarks.clj +++ b/scripts/benchmarks.clj @@ -335,3 +335,9 @@ (transform (walker number?) inc data) (transform (walker-old number?) inc data) )) + +(let [data (vec (range 1000)) insert-idx 500] + (run-benchmark "old versus new before-index implementation" + (setval (before-index-old insert-idx) -1 data) + (setval (before-index-new insert-idx) -1 data) + )) \ No newline at end of file diff --git a/src/clj/com/rpl/specter.cljc b/src/clj/com/rpl/specter.cljc index 8d76326..0c5b8e5 100644 --- a/src/clj/com/rpl/specter.cljc +++ b/src/clj/com/rpl/specter.cljc @@ -968,7 +968,7 @@ (defrichnav ^{:doc "Navigates to the empty space between the index and the prior index. For select navigates to NONE, and transforms to non-NONE insert at that position."} - before-index + before-index-old [index] (select* [this vals structure next-fn] NONE) @@ -980,6 +980,28 @@ (setval (srange index index) [v] structure) )))) +(defrichnav + ^{:doc "Navigates to the empty space between the index and the prior index. For select + navigates to NONE, and transforms to non-NONE insert at that position."} + before-index-new + [index] + (select* [this vals structure next-fn] + NONE) + (transform* [this vals structure next-fn] + (let [v (next-fn vals NONE)] + (if (identical? NONE v) + structure + (let [updated (concat (take index structure) [v] (drop index structure))] + (if (string? structure) + (apply str updated) + updated + ) + ))))) + +;; (temporarily) assign before-index-new to before-index so existing tests are exercised against it +;; to be removed before a final merge (wherein before-index-new is also renamed to before-index) +(def before-index before-index-new) + (defrichnav ^{:doc "Navigates to the index of the sequence if within 0 and size. Transforms move element at that index to the new index, shifting other elements in the sequence."} diff --git a/test/com/rpl/specter/core_test.cljc b/test/com/rpl/specter/core_test.cljc index 740bf3e..be5e22e 100644 --- a/test/com/rpl/specter/core_test.cljc +++ b/test/com/rpl/specter/core_test.cljc @@ -1609,7 +1609,8 @@ (deftest before-index-test (let [data [1 2 3] - datal '(1 2 3)] + datal '(1 2 3) + datastr "abcdef"] (is (predand= vector? [:a 1 2 3] (setval (s/before-index 0) :a data))) (is (predand= vector? [1 2 3] (setval (s/before-index 1) s/NONE data))) (is (predand= vector? [1 :a 2 3] (setval (s/before-index 1) :a data))) @@ -1617,6 +1618,7 @@ (is (predand= list? '(:a 1 2 3) (setval (s/before-index 0) :a datal))) (is (predand= list? '(1 :a 2 3) (setval (s/before-index 1) :a datal))) (is (predand= list? '(1 2 3 :a) (setval (s/before-index 3) :a datal))) + (is (predand= string? "abcxdef" (setval (s/before-index 3) (char \x) datastr))) )) (deftest index-nav-test