11.3.5 使用 cond 的递归示例

前面介绍的 triangle-recursively 版本是使用 if 特殊形式编写的。它也可以使用另一种名为 cond 的特殊形式来实现。特殊形式 cond 的名称是单词 ‘conditional’(条件)的缩写。

尽管 cond 特殊形式在 Emacs Lisp 源码中不像 if 那样常用,但其使用频率也足以值得对其进行讲解。

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 表达式求值时,它会依次对 cond 主体内一系列表达式中的第一个表达式的第一个元素(CAR,即真假测试表达式)进行求值。

如果真假测试返回 nil,则该表达式的其余部分(结果表达式)会被跳过,转而对下一个表达式的真假测试进行求值。当找到某个表达式的真假测试返回非 nil 值时,该表达式的结果部分会被求值。结果部分可以是一个或多个表达式。如果结果部分包含多个表达式,这些表达式会按顺序求值,并返回最后一个表达式的值。如果该表达式没有结果部分,则返回真假测试本身的值。

如果所有真假测试均不成立,则 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)))