2.2 求值 (Evaluation)
上一小节中,我们在顶层输入表达式,然后 Lisp 显示它们的值。在这节里我们深入理解一下表达式是如何被求值的。
在 Lisp 里, +
是函数,然而如 (+ 2 3)
的表达式,是函数调用。
当 Lisp 对函数调用求值时,它做下列两个步骤:
- 首先从左至右对实参求值。在这个例子当中,实参对自身求值,所以实参的值分别是
2
跟3
。- 实参的值传入以操作符命名的函数。在这个例子当中,将
2
跟3
传给+
函数,返回5
。
如果实参本身是函数调用的话,上述规则同样适用。以下是当 (/ (- 7 1) (- 4 2))
表达式被求值时的情形:
- Lisp 对
(- 7 1)
求值:7
求值为7
,1
求值为1
,它们被传给函数-
,返回6
。- Lisp 对
(- 4 2)
求值:4
求值为4
,2
求值为2
,它们被传给函数-
,返回2
。- 数值
6
与2
被传入函数/
,返回3
。
但不是所有的 Common Lisp 操作符都是函数,不过大部分是。函数调用都是这么求值。由左至右对实参求值,将它们的数值传入函数,来返回整个表达式的值。这称为 Common Lisp 的求值规则。
Note
逃离麻烦
如果你试着输入 Lisp 不能理解的东西,它会打印一个错误讯息,接着带你到一种叫做中断循环(break loop)的顶层。 中断循环给予有经验的程序员一个机会,来找出错误的原因,不过最初你只会想知道如何从中断循环中跳出。 如何返回顶层取决于你所使用的 Common Lisp 实现。在这个假定的实现环境中,输入 :abort
跳出:
> (/ 1 0)
Error: Division by zero
Options: :abort, :backtrace
>> :abort
>
附录 A 演示了如何调试 Lisp 程序,并给出一些常见的错误例子。
一个不遵守 Common Lisp 求值规则的操作符是 quote
。 quote
是一个特殊的操作符,意味着它自己有一套特别的求值规则。这个规则就是:什么也不做。 quote
操作符接受一个实参,并完封不动地返回它。
> (quote (+ 3 5))
(+ 3 5)
为了方便起见,Common Lisp 定义 '
作为 quote
的缩写。你可以在任何的表达式前,贴上一个 '
,与调用 quote
是同样的效果:
> '(+ 3 5)
(+ 3 5)
使用缩写 '
比使用整个 quote
表达式更常见。
Lisp 提供 quote
作为一种保护表达式不被求值的方式。下一节将解释为什么这种保护很有用。