3

我正在阅读Practical Common Lisp。在第 11 章中,它谈到了排序:

通常,您在排序后不会关心序列的未排序版本,因此在排序过程中允许SORTSTABLE-SORT销毁序列是有意义的。但这确实意味着您需要记住编写以下内容:

(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*因此很明显该值已更改。

4

2 回答 2

8

如果您希望变量之后包含排序序列的正确值,则有必要进行赋值。如果您不关心这一点并且只想要 的返回值sort,则不需要赋值。

有两个原因。首先,允许实现使用非破坏性复制来实现破坏性操作。其次,对列表的破坏性操作可以置换 conses,使得传递给操作的值不再指向序列的第一个 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)
于 2015-04-18T04:21:21.583 回答
6

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

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

在 Common Lisp 中,排序功能可能具有破坏性。当它得到一个用于排序的向量时,它可以返回相同的向量或一个新的向量。这取决于实施。在一种实现中,它可能返回相同的向量,而在另一种实现中,它可能返回一个新向量。但无论如何,它们都会被排序。

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

记住 唯一可以确定的是:SORT 函数返回一个排序后的序列作为它的值。

于 2015-04-18T04:23:32.917 回答