给定以下树(或 Clojure 中的任何其他形式,包括映射和向量):
'( (a b) (c d) )
我想在 Clojure 中生成一个映射,该映射根据整个表单的深度优先遍历对每个子表单进行索引,并提供表单子项(如果有)索引的向量(或列表)。
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]
到目前为止,我只设法使用clojure.walk来生成第一部分(索引子表单),但我对如何生成孩子的索引也感到困惑。我的代码附加在最后并产生:
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}
因此,子表单的索引是根据深度优先遍历正确生成的,但我不知道如何获得每个子表单的子表单的索引。我尝试使用 zippers 模块,但看不到如何执行深度优先遍历来收集索引。
中途代码
(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))