Given the following tree (or any other form in Clojure including maps and vectors):
'( (a b) (c d) )
I would like to generate a map in Clojure that indexes each sub-form according to a depth-first traversal of the entire form and also provides a vector (or list) of the indices of the form's children (if any).
0 -> a []
1 -> b []
2 -> (a b) [0 1]
3 -> c []
4 -> d []
5 -> (c d) [3 4]
6 -> ( (a b) (c d) ) [2 5]
I have so far only managed to use clojure.walk to produce the first part (indexing the subforms) but I am baffled as to how to generate the indices of the children as well. My code is appended at the end and produces:
user=> (depthFirstIndexing '( (a b) (c d) ))
{6 ((a b) (c d)), 5 (c d), 4 d, 3 c, 2 (a b), 1 b, 0 a}
So the indexes to the sub-forms are generated correctly according to depth-first traversal but I don't see how I can obtain the indices of the children of every sub-form. I tried to use the zippers module but I couldn't see how to perform a depth-first traversal to collect the indices.
half-way there code
(use 'clojure.walk)
(defn depthFirstIndexing [aform]
(let [counter (atom -1)
idxToSubform (atom {})
]
(postwalk (fn [x]
(def idx (swap! counter inc))
(swap! idxToSubform assoc idx x)
x)
aform)
@idxToSubform))