这个功能在这里:
(defun test (a)
(if (equal a nil) 0)
(if (listp (car a)) (print "a")
(print "b"))
(test (cdr a))
)
如果0
是a
这是基本情况,我希望它返回nil
。然后,如果列表前面的元素是列表,则打印字母a
否则打印b
然后再次调用函数。为什么基本情况不会阻止无限循环?
答案 0 :(得分:3)
您的代码最终会出现堆栈溢出,因为无论test
检查结果如何,都会递归到nil
。
(defun test (a)
(if (equal a nil) 0) ; <-- problem is partly here...
(if (listp (car a))
(print "a")
(print "b"))
(test (cdr a))) ; <-- ...and partly down here
即使(equal a nil)
评估为T
且周围的if
评估为0
,您基本上也会忽略此结果,因为您要做的下一步是检查{是否{ {1}}是一个列表,无论前一个a
检查结果如何。最后,您再次致电nil
而不考虑比较结果。
请记住,Lisp中函数的结果是最后一次计算表达式的结果,这意味着如果您希望函数返回test
,则必须使0
成为最后一个计算表达式
以下代码的行为与您指定的相同:
0
(defun test (a)
(if (null a)
0
(progn
(if (listp (car a))
(print "a")
(print "b"))
(test (cdr a)))))
进行零检查。null
不是a
,那么只有这样,才会进一步检查nil
。为此,a
允许您评估表达式序列,并最终计算其最后一个表达式的结果。答案 1 :(得分:3)
其他答案很好地解释了你的问题;只有2个音符:
<强> COND 强>
至少有一个样式指南建议使用 if 并且喜欢 cond ;这样可以避免&#34;掉头问题&#34;:
(defun test (a)
(cond
((equal a nil) 0)
(t (if (listp (car a))
(print "a")
(print "b"))
(test (cdr a)))))
<强>返回强>
您可以从功能中提前返回;您的代码可以使用 return-from 子句:
(defun test (a)
(if (equal a nil) (return-from test 0))
(if (listp (car a))
(print "a")
(print "b"))
(test (cdr a)))
答案 2 :(得分:1)
因为您的基本案例仍然是打印和递归。之后它没有直接回归。
也许你想要这个:
(defun test (a)
(if (null a)
0
(progn (if (listp (car a))
(print "a")
(print "b"))
(test (cdr a)))))