2.3 数据 (Data)
Lisp 提供了所有在其他语言找的到的,以及其他语言所找不到的数据类型。一个我们已经使用过的类型是整数(integer),整数用一系列的数字来表示,比如: 256
。另一个 Common Lisp 与多数语言有关,并很常见的数据类型是字符串(string),字符串用一系列被双引号包住的字符串表示,比如: "ora et labora"
[3] 。整数与字符串一样,都是对自身求值的。
[3] | “ora et labora” 是拉丁文,意思是祷告与工作。 |
有两个通常在别的语言所找不到的 Lisp 数据类型是符号(symbol)与列表(lists),符号是英语的单词 (words)。无论你怎么输入,通常会被转换为大写:
> 'Artichoke
ARTICHOKE
符号(通常)不对自身求值,所以要是想引用符号,应该像上例那样用 '
引用它。
列表是由被括号包住的零个或多个元素来表示。元素可以是任何类型,包含列表本身。使用列表必须要引用,不然 Lisp 会以为这是个函数调用:
> '(my 3 "Sons")
(MY 3 "Sons")
> '(the list (a b c) has 3 elements)
(THE LIST (A B C) HAS 3 ELEMENTS)
注意引号保护了整个表达式(包含内部的子表达式)被求值。
你可以调用 list
来创建列表。由于 list
是函数,所以它的实参会被求值。这里我们看一个在函数 list
调用里面,调用 +
函数的例子:
> (list 'my (+ 2 1) "Sons")
(MY 3 "Sons")
我们现在来到领悟 Lisp 最卓越特性的地方之一。Lisp的程序是用列表来表示的。如果实参的优雅与弹性不能说服你 Lisp 表示法是无价的工具,这里应该能使你信服。这代表着 Lisp 程序可以写出 Lisp 代码。 Lisp 程序员可以(并且经常)写出能为自己写程序的程序。
不过得到第 10 章,我们才来考虑这种程序,但现在了解到列表和表达式的关系是非常重要的,而不是被它们搞混。这也就是为什么我们需要 quote
。如果一个列表被引用了,则求值规则对列表自身来求值;如果没有被引用,则列表被视为是代码,依求值规则对列表求值后,返回它的值。
> (list '(+ 2 1) (+ 2 1))
((+ 2 1) 3)
这里第一个实参被引用了,所以产生一个列表。第二个实参没有被引用,视为函数调用,经求值后得到一个数字。
在 Common Lisp 里有两种方法来表示空列表。你可以用一对不包括任何东西的括号来表示,或用符号 nil
来表示空表。你用哪种表示法来表示空表都没关系,但它们都会被显示为 nil
:
> ()
NIL
> nil
NIL
你不需要引用 nil
(但引用也无妨),因为 nil
是对自身求值的。