为什么这个Lisp函数总是给我一个堆栈溢出?
此功能在此处:为什么这个Lisp函数总是给我一个堆栈溢出?,lisp,Lisp,此功能在此处: (defun test (a) (if (equal a nil) 0) (if (listp (car a)) (print "a") (print "b")) (test (cdr a)) ) 如果a是nil,我希望它返回0,这是基本情况。然后,如果列表前面的元素是列表,则打印字母a,否则打印b,然后再次调用函数。为什么基
(defun test (a)
(if (equal a nil) 0)
(if (listp (car a)) (print "a")
(print "b"))
(test (cdr a))
)
如果a是nil,我希望它返回0,这是基本情况。然后,如果列表前面的元素是列表,则打印字母a,否则打印b,然后再次调用函数。为什么基本情况不能阻止无限循环?因为基本情况之后仍然是打印和递归。之后它没有直接返回 也许你想要这个:
(defun test (a)
(if (null a)
0
(progn (if (listp (car a))
(print "a")
(print "b"))
(test (cdr a)))))
您的代码最终会出现堆栈溢出,因为无论nil检查的结果如何,您都会递归到测试中 请注意,您可以使用null进行nil检查。 如果a不是零,那么并且只有在那时,a才被进一步检查。为此,progn允许您计算表达式序列,并最终计算为最后一个表达式的结果。
其他答案很好地解释了你的问题;只有两个注释: 康德 至少有一个风格指南建议不要使用if和preferencecond;这本可以避免跌落问题:
(defun test (a)
(cond
((equal a nil) 0)
(t (if (listp (car a))
(print "a")
(print "b"))
(test (cdr a)))))
返回
您可以从函数中提前返回;您的代码将使用returnfrom子句:
我几乎要投你一票了,但是你的if缩进被取消了。标准缩进是将then和else与测试在同一个缩进处对齐。我已经有很长一段时间没有做任何与Lisp相关的事情了,但我看到它是双向的。有没有类似于权威风格指南的东西?我倾向于使用,尽管它不是特定于CL的。但即使是常见的lisp缩进也同意这一点。谢谢你的推荐。我同意并会解决这个问题。好的,这就是我想做的。。。如果nil返回0 else如果a是list print a else如果a不是list print b返回函数,且cdr aIn实现执行尾部调用优化,那么这将是一个无限循环。
(defun test (a)
(if (null a)
0
(progn
(if (listp (car a))
(print "a")
(print "b"))
(test (cdr a)))))
(defun test (a)
(cond
((equal a nil) 0)
(t (if (listp (car a))
(print "a")
(print "b"))
(test (cdr a)))))
(defun test (a)
(if (equal a nil) (return-from test 0))
(if (listp (car a))
(print "a")
(print "b"))
(test (cdr a)))