Last week, I was trying to write an algorithm with Zippers to update a specific element in a nested data structure, How to move an element within a structure, possibly with zippers?

My answer there solves the problem for that exact structure, nesting more elements breaks the algorithm.

That made think, is it possible to write a generic algorithm with Zippers to update a specific data in a nested data structure (no matter how nested it is)? Or Zippers are only when you know your steps exactly?

I need to understand that, properly I'm trying to make Zippers do something that isn't what Zippers are created for.

2

There are 2 best solutions below

0
On

Absolutely you can use zippers in this way, as you can move around a zip in any direction you choose. As an example have a look at the zip-visit library, which offers arbitrary visiting over zippers, with the ability to change nodes as required.

An example taken from the docs:

(def s "<div><span id='greeting'>Hello</span> <span id='name'>Mr. Foo</span>!</div>")
(def root (z/xml-zip (xml/parse (java.io.ByteArrayInputStream. (.getBytes s)))))

(defn replace-element [id replacement]
  (visitor :pre [n s]
    (if (= (:id (:attrs n)) id) {:node replacement})))

user=> (pprint (:node (visit root nil [(replace-element "name" "Mr. Smith")])))
{:tag :div,
 :attrs nil,
 :content
 [{:tag :span, :attrs {:id "greeting"}, :content ["Hello"]}
  "Mr. Smith"
  "!"]}

Of course, you can also use simple walking to accomplish similar tasks, an example of which is on this SO question on traversing maps.

0
On

Chiron

Take a look at data.zip as it provides the ability to chain predicates to get all the records of interest as well as update nodes.