更简单的Lisp函数不起作用

更简单的Lisp函数不起作用,lisp,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)))))

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

 (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)))))
           )
(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

这将返回周期内的元素数,无论是否列出。我看不出我错在哪里。还有一个问题,当我调用(测试1)或对任何atom进行测试时,它会崩溃。当然,您不能获取原子的cdr,但是我可以做什么错误检查呢?我可以做些什么改变来让这个荒谬的函数工作?

第一个块不工作,因为函数“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))))))
第二个问题是check(listpa)。您应该检查第一个元素是否是list,而不是整个list是list(listp(cara))

我不知道,你用的是什么方言。在大多数情况下,表格“cond”是可用的,而不需要特殊的表格“return from”。因此,您可以按如下方式重写函数:

 (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)))))
           )
(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

第一个块不起作用,因为函数“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))))))
第二个问题是check(listpa)。您应该检查第一个元素是否是list,而不是整个list是list(listp(cara))

我不知道,你用的是什么方言。在大多数情况下,表格“cond”是可用的,而不需要特殊的表格“return from”。因此,您可以按如下方式重写函数:

 (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)))))
           )
(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


好的,我很遗憾向您展示了来自示例的
返回;-)再一次,
cond
会把你救在这里。我不确定cond是什么。。。这意味着它的工作方式。它是在发现第一条true语句后检查每条语句,还是只执行第一条true语句?这是我没有使用它的唯一原因。再次感谢您的耐心和帮助@user3270407如果您使用CommonLisp,这里有关于cond的信息:在大多数Lisp中,cond的行为是相同的。只有第一个是正确的。请参阅。好的,我很遗憾向您展示了来自
示例;-)的
返回再一次,
cond
会把你救在这里。我不确定cond是什么。。。这意味着它的工作方式。它是在发现第一条true语句后检查每条语句,还是只执行第一条true语句?这是我没有使用它的唯一原因。再次感谢您的耐心和帮助@user3270407如果您使用CommonLisp,这里有关于cond的信息:在大多数Lisp中,cond的行为是相同的。只有第一个是正确的。请参阅。如果
a
不是列表,为什么不返回0?函数应该产生一个数字。是的,progn执行所有表单并返回最后一个表单的结果。谢谢大家。我很抱歉一直问口齿不清的问题@尤里科瓦列夫不确定我能理解你
(测试1)
应该返回0,而不是
nil
@user3270407:如果您使用的是Common Lisp,那么实用Common Lisp的所有章节都可以在线获得:。还可以查看特定函数的通用Lisp Hyperspec文档。如果
a
不是列表,为什么不返回0?函数应该产生一个数字。是的,progn执行所有表单并返回最后一个表单的结果。谢谢大家。我很抱歉一直问口齿不清的问题@尤里科瓦列夫不确定我能理解你
(测试1)
应该返回0,而不是
nil
@user3270407:如果您使用的是Common Lisp,那么实用Common Lisp的所有章节都可以在线获得:。还可以查看常见的Lisp Hyperspec,以获取特定的逐函数文档。