11.3.5 使用 cond 进行递归的例子

先前描述的 triangle-recursively 版本是用 if 特殊形式编写的。它也可以使用另一种特殊形式称为 cond 来编写。特殊形式 cond 的名称是单词 ‘conditional’ 的缩写。

尽管在 Emacs Lisp 源代码中并不像 if 那样经常使用 cond 特殊形式,但它被足够频繁地使用,以便解释它是有道理的。

cond 表达式的模板如下:

(cond
 body…)

其中 body 是一系列列表。

更详细地写出来,模板如下:

(cond
 (first-true-or-false-test first-consequent)
 (second-true-or-false-test second-consequent)
 (third-true-or-false-test third-consequent)
  …)

当 Lisp 解释器评估 cond 表达式时,它评估第一个元素(即第一个表达式中的 CAR 或 true-or-false-test)。

如果 true-or-false-test 返回 nil,则跳过该表达式的其余部分,即 consequent,并评估下一个表达式的 true-or-false-test。当找到一个表达式,其 true-or-false-test 返回非 nil 的值时,将评估该表达式的 consequent。consequent 可以是一个或多个表达式。如果 consequent 包含多个表达式,则按顺序评估这些表达式,并返回最后一个的值。如果表达式没有 consequent,则返回 true-or-false-test 的值。

如果没有一个 true-or-false-test 测试为真,cond 表达式返回 nil

使用 cond 编写的 triangle 函数如下:

(defun triangle-using-cond (number)
  (cond ((<= number 0) 0)
        ((= number 1) 1)
        ((> number 1)
         (+ number (triangle-using-cond (1- number))))))

在这个例子中,如果数字小于等于 0,则 cond 返回 0;如果数字为 1,则返回 1;如果数字大于 1,则评估 (+ number (triangle-using-cond (1- number)))