如何格式化一棵树,使其能够与Clojure的zipper一起使用?

3
我正在为遗传编程问题创建s表达式树,并需要在演化过程中修改树的部分内容。我发现Clojure zipper函数似乎非常适合,但是我真的想不出如何使用它。
例如,假设我用以下代码创建一个zipper:
(def zipped (zip/seq-zip `(+ (- 1 2) 3)))

我理解这代表着一棵以+为根的树,看起来像这样:
   +
 -   3
1 2

我的拉链不这么认为:如果我用 (-> zipped zip/down zip/node) 请求第一个节点,它会给我返回+(这是正确的),但是 (-> zipped zip/down zip/down) 却没有带我到 -,而是返回了nil。事实上,(-> zipped zip/down zip/rights) 给出的是根节点右侧的所有子节点,这让我觉得我根本没有一棵树:
user> (-> zipped zip/down zip/rights)
((clojure.core/- 1 2) 3)

我相信我的树的表示是正确的,因为当我执行它们时,我得到了正确的答案。但是,zipper是否需要不同的布局呢?

2个回答

3
问题在于这里有两个不同的树的概念。你的树是一个值如何通过计算传递的图,但LISP考虑的是列表嵌套列表,并使用前缀表示法:
'(+ (- 1 2) 3) 也可以写成 (list + (list - 1 2) 3),实际上对应的树形结构如下:
+  .     3
   - 1 2

(-> zipped down node)会给你第一个元素,也就是一个原子+。 (-> zipped down down)因为第一个元素+是一个原子,所以会返回nil。 (-> zipped down right down node)会给你你想要的减号,因为它是表达式的第二个元素的第一个元素。


谢谢你的解释,让我明白了。 我认为我不需要按执行顺序遍历树,所以我可能仍然可以使用Zipper。 - Craig Glennie

1

树的结构与您所绘制的不同。根节点有3个子节点:+(- 1 2)3。当您从根节点开始执行down操作时,默认会选择最左边的子节点,因此您会看到+

要到达-,您需要调用以下命令:

user=> (-> zipped zip/down zip/right zip/down zip/node)
clojure.core/-

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接