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