我正在尝试创建一个函数,用于创建给定列表中所有子列表的列表。
我的意思是,当我有一个清单时:
(4 (a g b) g (1 2 3) g (4 5 6))
我想要一个清单:
((a g b) (1 2 3) (4 5 6))
目前我得到了什么:
(defun unterlisten_zurueckgeben (lst)
(let (unterlisten)
(cond ((endp lst) nil)
((listp (first lst))
(or (unterlisten_zurueckgeben (first lst))
(setq unterlisten (cons (first lst) (unterlisten_zurueckgeben (rest lst))))))
(t (unterlisten_zurueckgeben (rest lst))))
unterlisten))
似乎不起作用,我找不到我的错误。
答案 0 :(得分:3)
如果是这样,你可以写:
(defun unterlisten-zurueckgeben (lst)
(remove-if-not #'listp lst))
; or use #'consp if you don't want empty sublists
注意,在Lisp中,组合标识符的首选方法是使用破折号而不是下划线。
答案 1 :(得分:2)
所以你想只保留子列表。您可以使用remove-if
轻松完成此操作:
(defun remove-atoms (lst)
(remove-if #'atom lst))
在您的递归代码中存在以下问题:
(or (unterlisten_zurueckgeben (first lst))
(setq unterlisten (cons (first lst)
(unterlisten_zurueckgeben (rest lst))))))
如果(unterlisten_zurueckgeben (first lst))
的结果不是空列表(例如带有列表的列表),那么它将是整个事物的结果。
如果它不是nil
,那么您将本地绑定underlisten
更改为看似正常的结果。
由于cond
不是尾部表达式。函数的结果总是underlisten
。因此,对于您只是使用列表的其余部分递归的默认情况,结果永远不会返回,因为它将返回nil
(underlisten
的初始值)。
因此,即使您的递归滚动自己的解决方案也比它需要的复杂得多:
(defun remove-atoms (lst)
(cond ((endp lst) nil)
((listp (first lst))
(cons (first lst) (remove-atoms (rest lst))))
(t (remove-atoms (rest lst)))))