如果求值操作作用于某个列表内部的子列表,那么在对外层列表求值时,外层列表可以将内层列表首次求值返回的值作为信息使用。这也解释了为什么要先对内部表达式求值:它们返回的值会被外层表达式使用。
我们可以通过另一个加法示例来观察这一过程。将光标放在下面表达式的后面,然后输入 C-x C-e:
(+ 2 (+ 3 3))
数字 8 会出现在回显区。
执行过程是:Lisp 解释器首先对内部表达式 (+ 3 3) 求值,返回结果 6;随后对外层表达式求值,就像表达式是 (+ 2 6) 一样,返回结果 8。由于没有更外层的表达式需要求值,解释器会将该值打印在回显区。
现在就很容易理解快捷键 C-x C-e 所调用命令的名称了:eval-last-sexp。其中 sexp 是 “符号表达式(symbolic expression)” 的缩写,eval 是 “求值(evaluate)” 的缩写。该命令的作用是对最后一个符号表达式求值。
作为练习,你可以试着把光标放在表达式下一行的开头,或者放在表达式内部,再执行求值操作。
下面是同一个表达式:
(+ 2 (+ 3 3))
如果你把光标放在表达式后面空行的开头并输入 C-x C-e,回显区仍然会显示结果 8。现在试着把光标放在表达式内部。如果将光标放在倒数第二个右括号后面(看起来像是在最后一个括号上方),回显区会显示 6!这是因为命令此时对表达式 (+ 3 3) 进行了求值。
再把光标放在某个数字后面,输入 C-x C-e,你会得到数字本身。在 Lisp 中,对数字求值会直接得到该数字本身 — 这也是数字与符号的区别。如果对以 + 这类符号开头的列表求值,会得到计算机执行该名称所绑定函数定义中的指令后返回的值。如果单独对一个符号求值,则会发生不同的情况,我们将在下一节介绍。