第一章

amb 的功能

amb 的功能就是从它的参数里选出一个来让整个程序得到“有效的结 果”。“有效的结果”这个概念很模糊,什么叫做有效的结果?

为了定义“有效的结果”,我们首先定义一下叫做“无效的结果”, 或者叫做“失败的结果”。

(amb)

没有参数的 amb 被定义为是一个 *失败*。

看看下面这个表达式:

(if (amb #f #t)
    1
    (amb))

后面那个 (amb) 显然是失败,那么第一个 amb 应该选择哪一个参数 作为输出呢?如果它选 #f, 那么 if 判断条件为假,就会执行 (amb),导致整个表达式“失败”。

所以,为了避免失败,第一个 amb 不能选择 #f, 它只能选择 #t。 我们的表达式返回值是 1.

再来看一个例子:

(let ((x (list (amb 2 1 -2 5 8 18) (amb 9 8 2 4 14 20))))
  (assert (> (car x) (cadr x)))
  (display x))

x 是由 list 从两个 amb 的结果构造的 list. 这个表达式中间有一个断言,说 (car x) 必须 (cadr x). 那么那两个 amb 分别应该返回什么呢?我们可以从这个表达式的返 回结果看到:

(5 2)

第一个 amb 返回了 5, 第二个 amb 返回了 2. 这就叫做“有效的结 果”。

先别在你的 Scheme 解释器里敲上面的例子,它还没有定义呢! 别急,现在我们来看看 amb 用 Scheme 如何实现。

如果你真的着急,可以跳到 SchemeAmb#problems.