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实现的例子。