2.10 变量 (Variables)
let
是一个最常用的 Common Lisp 的操作符之一,它让你引入新的局部变量(local variable):
> (let ((x 1) (y 2))
(+ x y))
3
一个 let
表达式有两个部分。第一个部分是一组创建新变量的指令,指令的形式为 (variable expression) 。每一个变量会被赋予相对应表达式的值。上述的例子中,我们创造了两个变量, x
和 y
,分别被赋予初始值 1
和 2
。这些变量只在 let
的函数体内有效。
一组变量与数值之后,是一个有表达式的函数体,表达式依序被求值。但这个例子里,只有一个表达式,调用 +
函数。最后一个表达式的求值结果作为 let
的返回值。以下是一个用 let
所写的,更有选择性的 askem
函数:
(defun ask-number ()
(format t "Please enter a number. ")
(let ((val (read)))
(if (numberp val)
val
(ask-number))))
这个函数创建了变量 val
来储存 read
所返回的对象。因为它知道该如何处理这个对象,函数可以先观察你的输入,再决定是否返回它。你可能猜到了, numberp
是一个谓词,测试它的实参是否为数字。
如果使用者不是输入一个数字, ask-number
会持续调用自己。最后得到一个只接受数字的函数:
> (ask-number)
Please enter a number. a
Please enter a number. (ho hum)
Please enter a number. 52
52
我们已经看过的这些变量都叫做局部变量。它们只在特定的上下文里有效。另外还有一种变量叫做全局变量(global variable),是在任何地方都是可视的。 [2]
你可以给 defparameter
传入符号和值,来创建一个全局变量:
> (defparameter *glob* 99)
*GLOB*
全局变量在任何地方都可以存取,除了在定义了相同名字的区域变量的表达式里。为了避免这种情形发生,通常我们在给全局变量命名时,以星号作开始与结束。刚才我们创造的变量可以念作 “星-glob-星” (star-glob-star)。
你也可以用 defconstant
来定义一个全局的常量:
(defconstant limit (+ *glob* 1))
我们不需要给常量一个独一无二的名字,因为如果有相同名字存在,就会有错误产生 (error)。如果你想要检查某些符号,是否为一个全局变量或常量,使用 boundp
函数:
> (boundp '*glob*)
T