Lisp 理解遞迴

2021-06-10 05:01:05 字數 1154 閱讀 2703

學習遞迴的學生有時會被鼓勵在紙上跟蹤遞迴函式的所有呼叫。這種練習可能會有誤導:程式設計師定義乙個遞迴函式的時候,通常不會考慮因為呼叫它而產生的所有呼叫。如果有人非得以這一的方式來考慮程式,那麼遞迴就是令人煩惱的,這可沒有什麼幫助。遞迴的好處是它的精確性,它讓我們以從更加抽象的方式來觀察演算法。你可以不用考慮呼叫函式時所產生的所有的呼叫,就能判斷出乙個遞迴函式是否是正確的。

要探明乙個遞迴函式是否按照我們的設想工作,你需要問的就是:它覆蓋了所有情況嗎?比如,這裡是乙個找出列表長度的遞迴函式:

(defun len (lst)

(if (null lst)

(+ (len (cdr lst)) 1)))

我們可以通過確定兩件事情來確保這個函式是正確的:

1. 它對列表長度為0的列表是可以正常工作的;

2. 假設它對於長度為n的列表能夠正常工作,那麼它對於長度為n+1的列表也能夠正常工作;

如果我們建立起這兩點,那麼我們就知道這個函式對於所有可能的列表都是正確的。

我們的定義很顯然符合第一點:如果lst是nil,函式立即返回0.現在我們假設函式對於長度為n的列表是可以正確工作的。那麼我們給它乙個長度為n+1的列表。我們的定義中說了:函式將返回這個列表的cdr的長度加上1.這個cdr就是乙個長度為n的列表。按照我們的假設我們知道,它的len就是n。那麼整個列表的len就是n+1.

這就是我們所有需要知道的東西了。理解遞迴的秘密非常像處理括號的秘密。你怎樣知道哪個括號匹配哪個?你不需要那麼做。你怎麼視覺化所有那些呼叫?你不需要那麼做。

對於更加複雜的遞迴函式,可能有更多的情況需要考慮,但是過程是一樣的。

我們這裡第乙個情況(這裡是長度為0的列表)是基本情況(base case)。當乙個遞迴函式不能按照預期工作時,通常是因為基本情況是錯誤的。完全丟失掉基本情況是乙個很常見的錯誤,就像在下面的錯誤的member定義中的一樣:

(defun our-member (obj lst)

(if (eql (car lst) obj)

lst(our-member obj (cdr lst))))

我們需要初始化空(null)測試來確保當到到列表尾部並且沒有找到對應的元素的時候的時候遞迴能夠結束。我們這個版本的程式將會在搜尋不到對應值的時候進入無限迴圈。

能夠判斷乙個遞迴函式是否正確僅僅是理解遞迴的一部分,另一部分是能夠將你想做的用遞迴函式寫出來。

乙個簡單的lisp遞迴函式

defun mystery x y if null y nil if eql car y x 0 let z mystery x cdr y and z z 1 如果我們 mystery 6 019365 的話,就返回4。這個函式就是接受乙個實參和乙個列表,返回列表中第乙個和實參相等的元素前面有幾個...

lisp實戰文庫 LISP經典程式

一 繪製地形圖符號 1.點狀符號 對於點狀符號 其位置固定 數量較多 且一般都帶有一定的標註 可逐個製作屬性塊圖元 單獨插入。2.線狀符號 利用autocad 中強大的線型定義。3.面狀符號 由充填符號在面域內按一定的排列方式組合而成。目前auto cad 在建築設計 工程施工放樣得到廣泛應用 au...

lisp捕捉垂足 lisp函式詳解

auotlisp及vlisp函式全集 按字母順序排列按功能分類排列 212.ssget 一.功能 提示使用者選擇物件 圖元 並返回乙個選擇集。二.格式 ssget mode pt1 pt2 pt list filter list 三.說明 一 函式呼叫中各變元的說明 mode變元是指定物件 圖元 選...