2.2 求值 (Evaluation)

上一小节中,我们在顶层输入表达式,然后 Lisp 显示它们的值。在这节里我们深入理解一下表达式是如何被求值的。

在 Lisp 里, + 是函数,然而如 (+ 2 3) 的表达式,是函数调用。

当 Lisp 对函数调用求值时,它做下列两个步骤:

  1. 首先从左至右对实参求值。在这个例子当中,实参对自身求值,所以实参的值分别是 23
  2. 实参的值传入以操作符命名的函数。在这个例子当中,将 23 传给 + 函数,返回 5

如果实参本身是函数调用的话,上述规则同样适用。以下是当 (/ (- 7 1) (- 4 2)) 表达式被求值时的情形:

  1. Lisp 对 (- 7 1) 求值: 7 求值为 71 求值为 1 ,它们被传给函数 - ,返回 6
  2. Lisp 对 (- 4 2) 求值: 4 求值为 42 求值为 2 ,它们被传给函数 - ,返回 2
  3. 数值 62 被传入函数 / ,返回 3

但不是所有的 Common Lisp 操作符都是函数,不过大部分是。函数调用都是这么求值。由左至右对实参求值,将它们的数值传入函数,来返回整个表达式的值。这称为 Common Lisp 的求值规则。

Note

逃离麻烦

如果你试着输入 Lisp 不能理解的东西,它会打印一个错误讯息,接着带你到一种叫做中断循环(break loop)的顶层。 中断循环给予有经验的程序员一个机会,来找出错误的原因,不过最初你只会想知道如何从中断循环中跳出。 如何返回顶层取决于你所使用的 Common Lisp 实现。在这个假定的实现环境中,输入 :abort 跳出:

  1. > (/ 1 0)
  2. Error: Division by zero
  3. Options: :abort, :backtrace
  4. >> :abort
  5. >

附录 A 演示了如何调试 Lisp 程序,并给出一些常见的错误例子。

一个不遵守 Common Lisp 求值规则的操作符是 quotequote 是一个特殊的操作符,意味着它自己有一套特别的求值规则。这个规则就是:什么也不做。 quote 操作符接受一个实参,并完封不动地返回它。

  1. > (quote (+ 3 5))
  2. (+ 3 5)

为了方便起见,Common Lisp 定义 ' 作为 quote 的缩写。你可以在任何的表达式前,贴上一个 ' ,与调用 quote 是同样的效果:

  1. > '(+ 3 5)
  2. (+ 3 5)

使用缩写 ' 比使用整个 quote 表达式更常见。

Lisp 提供 quote 作为一种保护表达式不被求值的方式。下一节将解释为什么这种保护很有用。