Zipper in scheme › 前言 [#271]

zipper 是一种非常方便的数据结构,它允许我们替换复杂数据结构(例如树或 term)深处的项,而无需任何可变性。结果数据结构将尽可能多地与旧结构共享其组件 [见附录]。旧的数据结构仍然可用(这便于我们撤销该操作)。本质上,zipper 是一个“可更新”但纯函数式的数据结构游标。
Zipper is a very handy data structure that lets us replace an item deep in a complex data structure, e.g., a tree or a term, without any mutation. The resulting data structure will share as much of its components with the old structure as possible [see addendum]. The old data structure is still available (which can be handy if we wish to 'undo' the operation later on). Zipper is essentially an `updateable' and yet pure functional cursor into a data structure.

有用的参考:
  • http://www.nist.gov/dads/HTML/zipper.html
  • http://citeseer.ist.psu.edu/hinze01web.html
Useful references:
        http://www.nist.gov/dads/HTML/zipper.html
        http://citeseer.ist.psu.edu/hinze01web.html

zipper 是一种由定界延续具体化而来的数据结构。不知何故,这个想法在 zipper 领域并不常见。因为 scheme 有一等支持的定界延续,我们可以更容易地派生和使用 zipper。
Zipper is a _delimited continuation_ reified as a data structure. Somehow that idea is not commonly discussed in the zipper literature. Because Scheme has first-class and delimited continuations, we can derive and use zipper far more easily.

本文将给出 zipper 的派生及其使用示例:交换两棵树的两个分支。该使用示例是遗传编程中典型的交叉操作。
Given below is a derivation of zipper and an example of its use: swapping out of two branches of a two trees. The latter is a typical cross-over operation in genetic programming.

[email protected] (Noel Welsh) 在消息中写

news:<[email protected]>...
我想以纯函数式的方式进行交叉,我设想的算法是:
  • 计算两棵树中每棵树的节点数
  • 选择 0 ...(节点数 - 1)之间的随机整数,在这个(整数索引的)节点进行交叉。
[email protected] (Noel Welsh) wrote in message
news:<[email protected]>...
I would like to do the crossover in a purely functional manner.  The
algorithm I envisage is:
  - Count the number of nodes for each of the two trees
  - Choose an random integer between 0 ... (number of nodes - 1)
    This is the node where crossover will take place.

正如上文指出的,我们不需要通过计数来从树中选择随机节点。选择节点后,我们可以使用 eq? 测试来向下拉开树中的该节点。然而,在下文中,为了简单起见,我们跳过随机选择,按深度优先顺序和节点索引选择节点。
As pointed out earlier, we don't need counting to select a random node from a tree. After we selected the node, we can zip down to that node in the tree using the eq? test. In the following however, we skip the random selection for simplicity and thus we shall be selecting nodes by their index in the depth-first order.