如何在没有地图的情况下在 Lisp 中创建子列表列表?

How to create a list of sublists in Lisp without map?

我正在尝试创建一个函数来创建给定列表中所有子列表的列表。

我的意思是,当我有一个列表时:

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

似乎不​​起作用,我找不到我的错误。

如果是这样你可以写:

(defun unterlisten-zurueckgeben (lst)
    (remove-if-not #'listp lst))
 ; or use #'consp if you don't want empty sublists

请注意,在 Lisp 中,组合标识符的首选方式是使用破折号而不是下划线。

所以你只想保留子列表。您可以使用 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,那么您将 local 绑定 underlisten 更改为看起来不错的结果。

因为 cond 而不是 尾部表达式。函数的结果总是 underlisten 是什么。因此,对于默认情况下,您只是对列表的其余部分进行递归,结果永远不会 returned,因为它将 return nilunderlisten 的初始值)。

因此,即使是您的递归式自己解决方案也比需要的复杂得多:

(defun remove-atoms (lst)
  (cond ((endp lst) nil)
        ((listp (first lst))
         (cons (first lst) (remove-atoms (rest lst))))
        (t (remove-atoms (rest lst)))))