Lisp 入门/第十章 小例子
从一到八章,我们讲解了许多函数,有好多不是公理,我们来一一实现它们(以及一些新的函数)。
这些函数系统都有提供,我们重新发明一遍轮子。这些轮子的简单程度可以说是令人发指。
NULL函数
编辑NULL函数用于检测表是否为空,或者元素是否为nil。
(defun null2 (x) (cond ((equal x nil) t) (t nil))))
解释:如果参数x与nil相等,就返回t,否则返回nil。这和逻辑学上的not函数是一致的(但null函数的应用范围更广,因为它可以应用于表)。
And函数
编辑>(defun and2 (x y) (cond ((equal x nil) nil) ((not (equal y nil)) t) (t nil)))
Or函数
编辑>(defun or2 (x y) (cond ((equal x t) t) ((equal y t) t)))
Last 函数的表示
编辑>(defun last2 (x) (cond ((equal (cdr x) nil) x) (t (last2 (cdr x)))))
Length函数的表示
编辑下面讲如何计算一个表x的长(即元素个数)度。
>(defun len (x) (cond ((null x) 0) (t (+ (len (cdr x)) 1))))
递归式是(len (cdr x)) ,终结条件是(null x)为真。
Append函数的表示
编辑设参数形式是x和y。很容易分析出来,递归式是(cons (car x) (append2 (cdr x) y)),终结条件是当x为NIL时,返回y。
>(defun append2 (x y) (cond ((eq x nil) y) (t (cons (car x) (append2 (cdr x) y)))))
Equal函数的表示
编辑设参数形式是x和y。很容易分析出来,递归式是(equal (cdr x) (cdr y)),递归条件是(equal (car x) (car y)),终止条件是(equal (cdr x) nil)或者(equal (cdr y) nil)或者((atom x) (equal x y))
(defun equal2 (x y)
(cond
((null x) (not y))
((null y) (not x))
((atom x) (eq x y))
((atom y) (eq x y))
((not (equal2 (car x) (car y))) nil)
(t (equal2 (cdr x) (cdr y)))
)
)
代码解释:
((null x) (not y))
首先,如果x为空,说明遇到了x列表的末尾,这时检测y列表是否也到了,如果到了(此时我们知道之前的元素都相等),那么返回真,否则返回假。
((null y) (not x))
如果y到了末尾,一样处理。
((atom x) (eq x y))
如果x是一个原子,说明函数是从(equal2 (car x) (car y))字句进入的,且(car x)的结果为原子。这时函数就可以结束了,返回x=y的结果。
((atom y) (eq x y))
如果y是一个原子,说明函数是从(equal2 (car x) (car y))字句进入的,且(car y)的结果为原子。这时函数就可以结束了,返回x=y的结果。
(t (equal2 (cdr x) (cdr y)))
否则的情况,我们就递归。
总结,大家可以发现,其实这个函数的递归路径有两个。
If函数的表示
编辑用cond可以实现if函数。实际上,在类c语言中,if语句强调的是程序的走向,但在Lisp中,程序的走向可以忽略(从某种意义上),而强调的是返回值。
>(defun if2 (p e1 e2)
(cond (p e1) (t e2))
)
IF2
--需要一个while实现的例子。