我正在阅读 Practical Common Lisp 。在chapter 11,中,它说明了有关排序的内容:
通常,在对序列进行排序后,您不会关心序列的未排序版本,因此允许
SORT
和STABLE-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*
的评估,因此很清楚该值已被更改。
答案 0 :(得分:8)
如果您希望变量在之后包含正确的排序序列值,则必须执行赋值。如果您不关心它并且只想要sort
的返回值,则不需要分配。
这有两个原因。首先,允许实现使用非破坏性复制来实现破坏性操作。其次,列表上的破坏性操作可以置换对象,使得传递给操作的值不再指向序列的第一个缺点。
以下是第二个问题的示例(在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)
答案 1 :(得分:6)
变量不能被sort函数改变,因为sort函数根本不知道变量。
所有sort函数get都是向量或列表,但不是变量。
在Common Lisp中,sort函数可能具有破坏性。 当它获得用于排序的向量时,它可以返回相同的向量或新的向量。这取决于实现。在一个实现中,它可以返回相同的向量,而在另一个实现中,它可以返回新的向量。但无论如何,它们都会被分类。
如果有一个变量,它指向一个序列,并且作者希望它在排序后指向一个已排序的序列:将变量设置为排序操作的结果。否则可能存在这样的情况,即在潜在破坏性排序之后,变量不会指向SORT结果,但仍然是未排序或以其他方式更改的序列。在矢量的情况下,这可以是旧的和未分类的矢量。
<强>记住强> 您唯一可以确定的是:SORT函数返回一个排序序列作为其值。