From 1b4a7d3d593422acc891ad75b602539cc9988d67 Mon Sep 17 00:00:00 2001 From: nathanmarz Date: Sun, 13 Aug 2017 07:49:08 -0400 Subject: [PATCH] add INDEXED-VALS navigator --- src/clj/com/rpl/specter.cljc | 40 ++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/clj/com/rpl/specter.cljc b/src/clj/com/rpl/specter.cljc index ea3df84..e15669a 100644 --- a/src/clj/com/rpl/specter.cljc +++ b/src/clj/com/rpl/specter.cljc @@ -994,6 +994,46 @@ structure ))) +(defnav + ^{:doc "Navigate to [index elem] pairs for each element in a sequence. Changing in index in transforms + has same effect as `index-nav`. Indices seen during transform take into account any shifting + resulting from prior sequence elements changing indices."} + INDEXED-VALS + [] + (select* [this structure next-fn] + ;; could be more efficient with a primitve mutable field + (let [i (i/mutable-cell -1)] + (doseqres NONE [e structure] + (i/update-cell! i inc) + (next-fn [(i/get-cell i) e]) + ))) + (transform* [this structure next-fn] + (let [i (i/mutable-cell 0) + indices (i/mutable-cell (-> structure count range vec))] + (reduce + (fn [s e] + (let [curri (nth (i/get-cell indices) (i/get-cell i)) + [newi newe] (next-fn [curri e])] + (if (> newi curri) + (i/update-cell! indices + (fn [ii] + (loop [j (inc curri) + s ii] + (let [news (update s j dec)] + (if (< j newi) + (recur (inc j) news) + news + )))))) + (i/update-cell! i inc) + (->> s + (setval (nthpath curri) newe) + (setval (index-nav curri) newi) + i/spy + ))) + structure + structure + )))) + (defrichnav ^{:doc "Navigates to result of running `afn` on the currently navigated value."} view