【发布时间】:2011-01-20 19:50:48
【问题描述】:
功能:
给定一个列表,lst 返回列表内容的所有排列,长度恰好为 k,如果未提供,则默认为列表长度。
(defun permute (lst &optional (k (length lst)))
(if (= k 1)
(mapcar #'list lst)
(loop for item in lst nconcing
(mapcar (lambda (x) (cons item x))
(permute (remove-if (lambda (x) (eq x item)) lst)
(1- k))))))
问题: 我在连接到 sbcl 的 emacs 中使用 SLIME,我还没有做太多的自定义。该函数适用于较小的输入,例如 lst = '(1 2 3 4 5 6 7 8) k = 3,这在实践中主要用于。但是,当我连续两次使用大输入调用它时,第二次调用永远不会返回,并且 sbcl 甚至不会出现在顶部。这些是 REPL 的结果:
CL-USER> (time (nth (1- 1000000) (permute '(0 1 2 3 4 5 6 7 8 9))))
Evaluation took:
12.263 seconds of real time
12.166150 seconds of total run time (10.705372 user, 1.460778 system)
[ Run times consist of 9.331 seconds GC time, and 2.836 seconds non-GC time. ]
99.21% CPU
27,105,349,193 processor cycles
930,080,016 bytes consed
(2 7 8 3 9 1 5 4 6 0)
CL-USER> (time (nth (1- 1000000) (permute '(0 1 2 3 4 5 6 7 8 9))))
而且它永远不会从第二次调用中恢复过来。我只能猜测出于某种原因我对垃圾收集器做了一些可怕的事情,但我看不到是什么。有人有什么想法吗?
【问题讨论】:
-
发生这种情况时,您的 inferior-lisp 缓冲区中有什么有趣的东西吗?
-
为什么不中断 SBCL 并查看回溯它的作用?
-
作为对所有回答者的一般性问题。看起来我正在制造的垃圾量确实是问题所在。有没有很好的文章解释如何解决这样的问题?我做了一些我认为会有所帮助的事情,但总的来说,它们实际上使情况变得更糟。
标签: recursion lisp common-lisp slime sbcl