我想尝试一些Common Lisp。我已经习惯了大括号的命令式语言,而且我仍然无法绕过Lisp风格的思维和语法。
下面是我正在尝试编写的排列函数。它目前已经破裂。
如果我用
运行此功能(permutations '(1 2 3))
我可以在标有“和此处”的断点处看到,在此点生成诸如(2 3),(3 2),(1 3)之类的列表。但是然后通过在SLIME中运行跟踪,我看到置换函数在该调用之后返回(2),(3)和(1)(在lisp中的第一项)。顶级函数然后返回nil(我也不明白)。
(defun permutations (coll)
(if (= 1 (length coll))
(print (list (first coll)))
(loop for el in coll do
(map 'list #'(lambda (combos)
(if
(break "you got here with arguments ~:S." (listp combos))
(cons el combos)
(break "and here: ~:S " (list el combos))))
(permutations (remove el coll))
))))
我在这里做错了什么?提前感谢您的帮助。
编辑: 这是我在更改功能以回应jlahd的评论后所拥有的。这回来了 (((1((2 3)))(1((3 2))))((2((1 3)))(2((3 1))))((3((1 2)) )(3((2 1)))))用原始例子调用时。还没有想出如何修复嵌套列表的事情。
(defun permutations (coll)
(if (= 1 (length coll))
(print (list (first coll)))
(loop for el in coll collect
(map 'list #'(lambda (combos)
(list el combos))
(permutations (remove el coll))
))))
编辑: 好的,谢谢大家的帮助!以下是我对Rörd和wxvxw的评论之后的看法。 运行并返回((1 2 .3)(1 3.2)(2 1.3)(2 3.1)(3 1.2)(3 2.1))。我不确定这里的“点对”符号与普通列表相比意味着什么,但除此之外这看起来还不错。
(defun permutations (coll)
(if (not (cdr coll))
(list (first coll))
(loop for el in coll nconc
(mapcar #'(lambda (combos)
(cons el combos))
(permutations (remove el coll))
))))
答案 0 :(得分:2)
您正在放弃在loop
中收集的所有数据。将do
更改为collect
,您就更远了。