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實現的例子。