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 是一个排序序列作为它的值。
我正在阅读 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
andSTABLE-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 是一个排序序列作为它的值。