2

所以我是 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。

我的问题是:为什么第一个功能可以,而第二个功能却不行,因为它们本质上是在做同样的事情?

4

2 回答 2

7

如果你打电话,说,,(suma2 1 2 3)L是列表(1 2 3)。然后你会打电话(suma2 (cdr L)),即(suma2 '(2 3))。在该调用L中将是 list ((2 3)),即包含单个元素的列表: list (2 3)。现在它将(suma2 (cdr L))再次调用,这次(cdr L)是空列表,所以在下一次调用L中是一个包含空列表的列表。由于这仍然是一个包含一个元素的列表,它会一次又一次地递归。L永远不会遇到为空的情况,因为L将始终是一个仅包含一个元素的列表:(cdr L).

因此,您应该将suma2函数更改为接受一个列表而不是可变数量的参数(然后将其调用为(suma2 (list 1 2 3))or(suma2 '(1 2 3))而不是(suma2 1 2 3)),或者使用将列表的内容作为其参数而不是列表本身apply进行调用。suma2

于 2013-10-09T23:05:04.360 回答
5

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

你希望你的函数被这样调用:

(suma2 1 2 3 4)

但第一次递归调用等价于:

(suma2 '(2 3 4))

您传递一个列表,其中需要单个元素。请参阅APPLY.

于 2013-10-09T23:04:55.430 回答