Common lisp 用两种方法展平列表:(i)使用MAPCAN和(ii)使用LOOP

Common lisp 用两种方法展平列表:(i)使用MAPCAN和(ii)使用LOOP,common-lisp,Common Lisp,我的教授给我们布置了一个关于clisp的复习作业。一个练习是通过三种方式实现相同的目标:返回给定列表中所有正整数的平坦列表 现在,我真正喜欢的方法只有一种,使用cons和递归,但他希望我使用mapcan和循环(我怀疑lisp不是他的首选语言,因为这种编码风格感觉非常抵制lisp的本质)。我很难想出如何使用循环来实现这一点……我想我需要先开始一个列表 我为模糊的语言道歉,因为我真的不知道如何谈论使用函数式语言按程序编写。以下是我的第一次尝试 (defun posint-loop (l) (

我的教授给我们布置了一个关于clisp的复习作业。一个练习是通过三种方式实现相同的目标:返回给定列表中所有正整数的平坦列表

现在,我真正喜欢的方法只有一种,使用cons和递归,但他希望我使用mapcan和循环(我怀疑lisp不是他的首选语言,因为这种编码风格感觉非常抵制lisp的本质)。我很难想出如何使用循环来实现这一点……我想我需要先开始一个列表

我为模糊的语言道歉,因为我真的不知道如何谈论使用函数式语言按程序编写。以下是我的第一次尝试

(defun posint-loop (l)  
  (loop for i in l
        do (if (listp i)  
               (posint-loop i)  
               (if (integerp i)  
                   (if (> i 0)  
                       (append i) ; this doesn't work because there's nothing to
                                  ; start appending to!
                       nil)  
                   nil))))

要建立新的词汇绑定,请使用或的关键字。为了扩展现有列表,您可能需要使用;如果您需要原始订单,可以使用新列表

另一种方法是使用的和关键字


另一个提示:隐式创建一个新列表。

Mapcan将一个函数应用于列表的每个元素,期望该函数返回一个列表,然后将这些结果列表连接在一起。要将它应用于这个问题,您只需要处理顶级列表的每个元素。如果元素是一个列表,那么您需要递归地处理它。如果不是,则需要返回一个空列表(不会向最终结果中添加任何元素)或一个仅包含该元素的列表(只将该元素添加到最终结果中):

使用loop,您可以做几乎相同的事情,识别(mapcan f list)在功能上等同于(list ncoc(funcall f x)中x的循环)。有鉴于此,我们有:

(defun flatten3 (list)
  (loop for x in list
        nconc (cond 
               ((listp x) (flatten3 x))
               ((and (integerp x) (plusp x)) (list x))
               (t '()))))

也许你可以展示一下你想怎么做。我还想提出一个想法,你可能不是你的教授,而是一个不了解Lisp本质的人
(flatten2 '((a 1 -4) (3 5 c) 42 0))
;=> (1 3 5 42)
(defun flatten3 (list)
  (loop for x in list
        nconc (cond 
               ((listp x) (flatten3 x))
               ((and (integerp x) (plusp x)) (list x))
               (t '()))))