组合完整的函数定义

我们可以把这些表达式组合成一个可用的函数定义。 不过仔细观察后会发现,其中一个局部变量其实是多余的!

函数定义如下:

;;; First subtractive version.
(defun triangle (number-of-rows)
  "Add up the number of pebbles in a triangle."
  (let ((total 0)
        (number-of-pebbles-in-row number-of-rows))
    (while (> number-of-pebbles-in-row 0)
      (setq total (+ total number-of-pebbles-in-row))
      (setq number-of-pebbles-in-row
            (1- number-of-pebbles-in-row)))
    total))

按当前写法,这个函数可以正常工作。

不过,我们其实并不需要 number-of-pebbles-in-row

triangle 函数被执行时,符号 number-of-rows 会绑定到一个数字,获得初始值。 这个数字可以在函数体内被修改,就像局部变量一样, 完全不用担心这种修改会影响函数外部的变量值。 这是 Lisp 非常有用的特性; 这意味着在函数中凡是用到 number-of-pebbles-in-row 的地方, 都可以直接使用 number-of-rows

下面是写法更简洁的第二个版本:

(defun triangle (number)                ; Second version.
  "Return sum of numbers 1 through NUMBER inclusive."
  (let ((total 0))
    (while (> number 0)
      (setq total (+ total number))
      (setq number (1- number)))
    total))

简而言之,一个规范的 while 循环包含三部分:

  1. 一个判断条件,在循环执行合适次数后返回假。
  2. 一个表达式,在重复执行后会得到期望的结果。
  3. 一个表达式,用于修改传给判断条件的值, 使得循环在合适次数后条件变为假。