Fork me on GitHub
#specter
<
2023-05-04
>
sh5411:05:30

Is there any way to edit multiple bits of a zipper in one transform? If I do something like the following I get a stack overflow 😕:

(let [s [:a [:b [1 2 3]] [:c 3 4 5]]]
    (S/transform [SZ/VECTOR-ZIP
                  SZ/NEXT-WALK
                  #(= 3 (zip/node %))
                  SZ/NODE]
                 (constantly [:z 1 2 3])
                 s))
Obviously there are plenty of ways to do this without zippers but this is the simplest thing I can get to blow up. If I change (constantly [:z 1 2 3]) to (constantly [:z 1 2]) then it all works fine. My intuition would be that it finds everything in the path then applies the transform to things. But it looks like it keeps expanding the 3's until the stack gets blown.

sh5412:05:47

The following seems to solve this specific problem. I will see if it solved my actual problem.

(def BEFORE-END
  (S/recursive-path [] p
                  (S/if-path #(zip/end? (zip/next %))
                             S/STAY
                             [SZ/NEXT p])))

(S/declarepath ^{:doc "Navigate to every element reachable using calls
                     to PREV"}
             PREV-WALK)

(S/providepath PREV-WALK
             (S/stay-then-continue
              SZ/PREV
              PREV-WALK))

(let [s [:a [:b [1 2 3]] [:c 3 4 5]]]
    (S/transform [SZ/VECTOR-ZIP
                  BEFORE-END
                  PREV-WALK
                  #(= 3 (zip/node %))
                  SZ/NODE]
                 (constantly [:z 1 2 3])
                 s))