LISP和休息问题

时间:2013-10-09 22:58:15

标签: lisp common-lisp

所以我是LISP的新手,我正在玩几个基本的函数。

(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。

我的问题是:为什么第一个功能正常,第二个功能不是基本上做同样的事情?

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:5)

第二个函数( - > suma2)中的函数调用错误。

您希望像这样调用您的函数:

(suma2 1 2 3 4)

但是第一次递归调用等同于:

(suma2 '(2 3 4))

您传递一个列表,其中包含预期的单个元素。请参阅APPLY的文档。