Hi, everybody,

I'm just throwing this out to see if the Clojure core team agrees, and if 
they would like me to code something up and send a PR.

clojure.zip works great if you want to walk a tree and add nodes here and 
there -- append-child, insert-child, insert-left, and insert-right cover 
all the important use cases. If you want to walk a tree and filter nodes 
out, remove has you covered. I've discovered, though, that trying to *move* 
nodes is very cumbersome, far more than it needs to be.

The crux of the problem is here (to quote the API docs):

removefunction

Usage: (remove loc)

Removes the node at loc, returning the loc that would have preceded
it in a depth-first walk.


The problem is that remove "returns the loc that would have preceded" the 
removed node "in a depth-first walk". If I want to push a node down below its 
left/right sibling, or pull it up to become a sibling of its parent, or make it 
swap places with its left/right sibling, etc. etc., going to "the loc that 
would have preceded it in a depth-first walk" is useless. Once the node is 
removed, it's very hard to find my way back to the loc where I want to insert 
it.


I'm not saying that the API for remove is faulty -- it's perfect if your goal 
is just to filter nodes out. But functions are needed which can remove a node 
*and* return the loc above/to the left/to the right.


When I ran into this problem, I cracked open the source for clojure.zip, looked 
at the source for "remove", and coded this variant up:


(defn remove-and-up [loc]
  (let [[node {l :l, ppath :ppath, pnodes :pnodes, rs :r, :as path}] loc]
    (if (nil? path)
      (throw (new Exception "Remove at top"))
      (if (pos? (count l))
        (up (with-meta [(peek l)
                    (assoc path :l (pop l) :changed? true)]
                   (meta loc)))
        (with-meta [(make-node loc (peek pnodes) rs) 
                    (and ppath (assoc ppath :changed? true))]
                   (meta loc))))))


That removes a node, and returns the loc of its parent. My problem is now 
solved. But to a newbie programmer, that problem would have probably been 
insurmountable.


What do you think? Is adding a function or two to clojure.zip warranted?


Thanks, AD

-- 
-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to