【问题标题】:Unexpected List Duplication using Sort with Common Lisp使用带有 Common Lisp 的排序的意外列表重复
【发布时间】:2012-04-14 17:29:29
【问题描述】:

编辑:解决方案是在第一个 (let...) 表单中将 '(1) 替换为 (list 1)。这是因为我试图修改文字数据。谢谢您的帮助! (我会放弃投票,但显然你需要 15 声望......)

这是我在这个网站上的第一篇文章。

我今天解决了一些Project Euler 问题,在 Common Lisp 中遇到了一些意想不到的列表排序行为(嗯,至少对我而言):

我有一个函数可以找到数字 x 的所有正确除数:

(defun divisors (x)
    "Finds all of the proper divisors of x."
    (let ((sq (sqrt x)) (divs '(1)))
        (when (integerp sq) (push sq divs))
        (loop for i from 2 to (1- (floor sq)) do
        (let ((div (/ x i)))
            (when (integerp div)
                (push i divs)
                (push div divs))))
    divs))

这个功能很好用。例如:

(divisors 100)
==> (20 5 25 4 50 2 10 1)

每当我尝试对结果列表进行排序时,就会出现问题:

(sort (divisors 100) #'<)
==> (1 2 4 5 10 20 25 50)

嗯,效果很好。但是当我再次调用除数时会发生什么?

(divisors 100)
==> (20 5 25 4 50 2 10 1 2 4 5 10 20 25 50)

什么?也许如果我尝试不同的号码...

(divisors 33)
==> (11 3 1 2 4 5 10 20 25 50)

在我对结果列表进行排序后,来自先前查询的除数是持久的。如果我重新编译该函数,则在再次对结果列表进行排序之前不会出现错误。我假设我在函数定义的某个地方搞砸了,但我对 Lisp 很陌生,我找不到错误。嵌套的 (let...) 表单可能有问题吗?

提前致谢!

【问题讨论】:

    标签: lisp common-lisp


    【解决方案1】:

    经常被问到。

    您已修改文字数据。您需要使用新数据。使用函数 LIST 或函数进行复制。

    【讨论】:

    • 感谢您的回复!你能更明确一点吗?恐怕我不明白。
    • @Lisper '(1) 是一个列表文字。对文字使用破坏性操作的后果是未定义的,sort 是破坏性操作。使用list 函数构造列表。
    【解决方案2】:

    Rainer 是对的;如果不明显,可以通过此更改修复代码:

    (let ((sq (sqrt x)) (divs (list 1)))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-13
      • 1970-01-01
      • 1970-01-01
      • 2014-11-10
      相关资源
      最近更新 更多