表里山河
——《左传·僖公二十八年》
上一集我们讲了Lisp世界七个公理的前三个,这一集我们接着讲剩下的四个。
首先是三个表操作
(car x)要求x是一个表,它返回x中的第一个元素,例如:
> (car '(a b))
a (cdr x)同样要求x是一个表,它返回x中除第一个元素之外的所有元素组成的表,例如:
> (cdr '(a b c))
(b c) (cons x y)要求y是一个表,它返回一个表,这个表的第一个元素是x,其后是y中的所有元素,例如:
> (cons 'a '(b c))
(a b c)
> (cons 'a (cons 'b (cons 'c ())))
(a b c) 看到这里大家可能会问,为什么没有取表中除开头外其它某个位置上的元素的操作符,别急,等我们讲到地球人都知道的函数和递归你就知道该怎么办了,也许你现在已经想得差不多了?
接下来要介绍给大家的是构成程序逻辑的一个基本功能……条件分支,在Lisp中,它是由cond操作符完成的,cond是七个公理中最后一个也是形式最复杂的一个(欧几里德的最后一个公理也如是):
(cond (p1 e1) (p2 e2)...(pn en))
p1到pn为条件,e1到en为结果,cond操作符依次对p1到pn求值,直到找到第一个值为原子t(还记得吗?)的p,此时把对应的e作为整个表达式的值返回,例如:
> (cond ((eq 'a 'b) 'first)
((atom 'a) 'second))
second
好了,至此我们已经有了Lisp世界的所有基本公理,我们可以开始构建整个世界的规则了。
在这七个操作符中,除quote和cond之外,以其他的五个操作符开头的表达式总是要对它的所有自变量求值,然后产生结果,我们把这样的表达式叫做函数。
注1:quote不对它的自变量求值,cond只对从p1到第一个返回值为t的p及其对应的e求值,这和其他的操作符不同。
注2:本来想在这一节开始讲函数的,但是函数涉及的东西太多,所以我决定将它单独提出来作为一节,这次就先偷个懒。