更简单的Lisp函数无法正常工作

时间:2014-02-18 16:09:30

标签: lisp

我正在尝试创建一个计算列表中列表数量的函数。

 (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,但我可以做什么错误检查?我可以做些什么改变来使这个荒谬的功能发挥作用?

1 个答案:

答案 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