11.3.2 递归定义的组成部分

递归函数通常包含一个条件表达式,由三部分组成:

  1. 一个真假判断条件,决定函数是否再次被调用, 这里称为再次执行条件(do-again-test)
  2. 函数名。当这个名字被调用时, 会创建一个新的函数实例 — 相当于一个新机器人 — 并告知其任务。
  3. 一个每次调用都返回不同值的表达式, 这里称为步进表达式(next-step-expression)。 于是,传给新函数实例的参数 会与上一个实例不同。 这会让条件表达式(再次执行条件(do-again-test)) 在合适的重复次数后返回假。

递归函数可以比其他任何函数都简洁得多。 事实上,人们刚开始使用时, 常常会觉得它们简洁得近乎神秘而难以理解。 就像骑自行车一样,读懂递归函数定义需要一定技巧, 起初很难,之后就会觉得很简单。

递归有几种常见模式。 一种非常简单的模式如下:

(defun name-of-recursive-function (argument-list)
  "documentation..."
  (if do-again-test
    body...
    (name-of-recursive-function
         next-step-expression)))

每次递归函数被执行时,都会创建一个新实例并指派任务。 参数告诉实例该做什么。

参数会绑定到步进表达式的值。 每个实例都使用不同的步进表达式值运行。

步进表达式的值会被用于再次执行条件。

步进表达式返回的值会传给新的函数实例, 实例对其求值(或某种转换后的值)以决定继续还是停止。 步进表达式的设计目标是: 当函数不应再重复时,让再次执行条件返回假。

再次执行条件有时也被称为终止条件(stop condition), 因为它在返回假时会停止重复。