lisp中的破坏性排序

Destructive sorting in lisp

我正在阅读 Practical Common Lisp。在 chapter 11, 中,它说了关于排序:

Typically you won't care about the unsorted version of a sequence after you've sorted it, so it makes sense to allow SORT and STABLE-SORT to destroy the sequence in the course of sorting it. But it does mean you need to remember to write the following:

(setf my-sequence (sort my-sequence #'string<))

我尝试了以下代码:

CL-USER> (defparameter *a* #( 8 4 3 9 5 9 2 3 9 2 9 4 3)) 
*A*            
CL-USER> *a*
#(8 4 3 9 5 9 2 3 9 2 9 4 3)                                     
CL-USER> (sort *a* #'<)
#(2 2 3 3 3 4 4 5 8 9 9 9 9)
CL-USER> *a*
#(2 2 3 3 3 4 4 5 8 9 9 9 9)

在这段代码中,我们可以看到变量 *a* 已被 sort 函数更改。

那为什么书上说必须做作业呢?

我正在使用 SBCL + Ubuntu 14.04 + Emacs + Slime

编辑: 在@Sylwester 的评论之后,我添加了 *a* 的评估,因此很明显该值已更改。

如果你想让你的变量在之后包含排序序列的正确值,那么有必要进行赋值。如果您不关心这一点并且只想要 sort 的 return 值,则不需要赋值。

这有两个原因。首先,允许一个实现使用非破坏性复制来实现破坏性操作。其次,对列表的破坏性操作可以置换cons,使得传递给操作的值不再指向序列的第一个cons。

这是第二个问题的例子(运行在SBCL下):

(let ((xs (list 4 3 2 1)))
  (sort xs '<)
  xs)
=> (4)

如果我们添加赋值:

(let ((xs (list 4 3 2 1)))
  (setf xs (sort xs '<))
  xs)
=> (1 2 3 4)

排序函数无法更改变量,因为排序函数根本不知道变量。

排序函数得到的只是一个向量或列表,而不是变量。

在 Common Lisp 中,排序函数可能是破坏性的。 当它得到一个向量进行排序时,它可以return相同的向量或一个新的向量。这取决于实现。在一种实现中,它可能 return 相同的向量,而在另一种实现中,它可能 return 一个新向量。但无论如何它们都会被排序。

如果有一个变量,它指向一个序列,并且作者希望它在排序后指向一个排序后的序列:将变量设置为排序操作的结果。否则可能会出现这样的情况,在潜在的破坏性排序之后,变量不会指向 SORT 结果,但仍指向未排序或以其他方式更改的序列。在矢量的情况下,这可以是旧的和未排序的矢量。

记得 唯一可以确定的是:SORT 函数 return 是一个排序序列作为它的值。