我正在尝试创建一个计算列表中列表数量的函数。
(defun test (a)
(if (equal a nil) (return-from test 0))
(if (not (listp a)) (print "case a") (return-from test (+ 0 (test (cdr a))))
(print "case b")(return-from test (+ 1 (test (cdr a)))))
)
我不知道调试器是如何工作的,所以我尝试了一些带有print语句的新手调试。上面的代码甚至都没有执行。我不知道为什么。原始代码有效但给出错误答案如下:
(defun test (a)
(if (equal a nil) (return-from test 0))
(if (not (listp a)) (return-from test (+ 0 (test (cdr a))))
(return-from test (+ 1 (test (cdr a)))))
)
这是返回元素周期数,无论列表与否。我不知道我哪里出错了。另一个问题是,当我调用(测试1)或测试任何原子时,它会崩溃。当然,你不能拿一个原子的cdr,但我可以做什么错误检查?我可以做些什么改变来使这个荒谬的功能发挥作用?
答案 0 :(得分:4)
第一个块不起作用,因为函数“if”最多处理3个表单(条件然后是分支else分支)。如果你想在一个分支中做一些动作,你应该用progn包装它们:
(if (not (listp a))
(progn
(print "case a")
(return-from test (+ 0 (test (cdr a)))))
(progn
(print "case b")
(return-from test (+ 1 (test (cdr a))))))
第二个问题是检查(listp a)。你应该检查第一个元素是否是列表而不是整个列表是列表(listp(car a))。
我不知道,你正在使用什么方言的口齿不清。在大多数形式中,“cond”可用,并且不需要特殊形式“return-from”。因此,您可以按如下方式重写您的功能:
(defun test (a)
(cond
((not (listp a)) nil) ; "atom" case
((not a) 0) ; empty list case
((listp (car a)) ; first element is list
(print "case list")
(+ 1 (test (cdr a))))
(T ; fist element is not list
(print "case not list")
(test (cdr a))))) ; avoid adding zero because it has no effect