2013-10-09 66 views
2

所以我是LISP的新手,我正在玩幾個基本的總和功能。LISP&rest issue

(defun suma (&rest L) 
    (cond 
    ((null L) 0) 
    (T (+ (CAR L) (EVAL (CONS 'suma (CDR L))))) 
)) 


(defun suma2 (&rest L) 
    (cond 
    ((null L) 0) 
    (T (+ (car L) (suma2 (cdr L)))) 
)) 

第一個函數工作得很好。第二個函數給出這個錯誤:SB-KERNEL :: CONTROL-STACK-EXHAUSTED。

我的問題是:爲什麼第一個函數可以正常工作,而第二個不是當他們本質上正在做同樣的事情?

回答

7

如果你打電話說,(suma2 1 2 3)L將成爲名單(1 2 3)。然後您將致電(suma2 (cdr L)),即(suma2 '(2 3))。在那個調用L將是列表((2 3)),即包含單個元素的列表:列表(2 3)。現在它將再次調用(suma2 (cdr L)),這次(cdr L)是空列表,因此在下一次調用中L是一個包含空列表的列表。由於這仍然是一個包含一個元素的列表,它將再次遞歸併一次又一次。 L爲空的情況將永遠不會到達,因爲L將始終是一個只包含一個元素的列表:(cdr L)的結果。

所以,你應該要麼改變你的suma2函數接受一個列表,而不是參數可變數目的(然後稱其爲(suma2 (list 1 2 3))(suma2 '(1 2 3))代替(suma2 1 2 3)),或使用apply調用suma2與列表的內容及其參數而不是列表本身。

5

第二個函數( - > suma2)中的函數調用是錯誤的。

你期望要調用的函數是這樣的:

(suma2 1 2 3 4) 

但第一個遞歸調用是相同的:

(suma2 '(2 3 4)) 

你傳遞一個列表,其中單個元素的預期。請參閱APPLY的文檔。