我正在尝试学习一些 Common Lisp。我习惯于使用大括号命令式语言,但仍然难以理解 Lisp 风格的思维和语法。
下面是我正在尝试编写的排列函数。它目前已损坏。
如果我用
(permutations '(1 2 3))
我可以在标记为“and here”的断点处看到,此时正在生成诸如 (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))
))))