Common Lisp 排序函数从原始列表中删除一个元素
Common Lisp sort function removing an element from the original list
我正在使用 SBCL,当我按如下方式使用 sort
函数时,
CL-USER> (defparameter y '(5 7 2 9 4 6))
Y
CL-USER> y
(5 7 2 9 4 6)
CL-USER> (sort y #'>)
(9 7 6 5 4 2)
CL-USER> y
(7 6 5 4 2)
最大的元素(在本例中为 9)已从原始列表中删除。
想知道发生了什么事吗?
sort
,根据manual,
destructively sort sequences according to the order determined by the predicate function.
换句话说,它可以修改它的参数,你应该得到排序操作返回的值。
CL-USER> (defvar y (list 5 7 2 9 4 6))
Y
CL-USER> (setf y (sort y #'>))
(9 7 6 5 4 2)
CL-USER> y
(9 7 6 5 4 2)
注意,因为它可以修改它的参数,如果我们想避免这样的修改,应该用 copy-list
调用它:
CL-USER> (defparameter y '(5 7 2 9 4 6))
Y
CL-USER> (sort (copy-list y) #'<)
(2 4 5 6 7 9)
CL-USER> y
(5 7 2 9 4 6)
最后,请注意修改文字值,如 '(5 7 2 9 4 6)
,会产生未定义的行为,应避免。
(defvar *y* '(1 2 3))
所以*y*
指向(1 2 3)
。像这样。
*y*--->[*|*]--->[*|*]--->[*|*]---> NIL
| | |
v v v
1 2 3
现在,如果您评估 (sort *y* #'>
),那么 *y*
会首先评估,然后内容会传递给 sort
。不是变量,是内容!在函数 sort
中,没有对 *y*
的引用。 sort
得到的是对第一个 cons 单元格的引用。
现在,当 sort
将 3
移到前面时,它可以通过将一个新的 cons 单元格放在前面来实现(这是实现排序的一种方法)。但是 sort
永远无法更新 *y*
以引用不同的对象,因为它没有对 *y*
本身的引用,而是对 (1 2 3)
的第一个 cons 单元格的引用.
因此,sort
returns 一个排序列表,并且应该使用它作为结果,而不是使用指向原始参数的引用。原始参数列表可能已更改:
sort
也可能 具有破坏性。
注意:破坏性排序的确切行为在 Common Lisp 中未指定
因此实现可能会出现不同的副作用。例如,参见 CLISP
实现:
[1]> (defvar *y* '(1 2 3))
*Y*
[2]> (sort *y* #'>)
(3 2 1)
[3]> *y*
(3 2 1)
我正在使用 SBCL,当我按如下方式使用 sort
函数时,
CL-USER> (defparameter y '(5 7 2 9 4 6))
Y
CL-USER> y
(5 7 2 9 4 6)
CL-USER> (sort y #'>)
(9 7 6 5 4 2)
CL-USER> y
(7 6 5 4 2)
最大的元素(在本例中为 9)已从原始列表中删除。
想知道发生了什么事吗?
sort
,根据manual,
destructively sort sequences according to the order determined by the predicate function.
换句话说,它可以修改它的参数,你应该得到排序操作返回的值。
CL-USER> (defvar y (list 5 7 2 9 4 6))
Y
CL-USER> (setf y (sort y #'>))
(9 7 6 5 4 2)
CL-USER> y
(9 7 6 5 4 2)
注意,因为它可以修改它的参数,如果我们想避免这样的修改,应该用 copy-list
调用它:
CL-USER> (defparameter y '(5 7 2 9 4 6))
Y
CL-USER> (sort (copy-list y) #'<)
(2 4 5 6 7 9)
CL-USER> y
(5 7 2 9 4 6)
最后,请注意修改文字值,如 '(5 7 2 9 4 6)
,会产生未定义的行为,应避免。
(defvar *y* '(1 2 3))
所以*y*
指向(1 2 3)
。像这样。
*y*--->[*|*]--->[*|*]--->[*|*]---> NIL
| | |
v v v
1 2 3
现在,如果您评估 (sort *y* #'>
),那么 *y*
会首先评估,然后内容会传递给 sort
。不是变量,是内容!在函数 sort
中,没有对 *y*
的引用。 sort
得到的是对第一个 cons 单元格的引用。
现在,当 sort
将 3
移到前面时,它可以通过将一个新的 cons 单元格放在前面来实现(这是实现排序的一种方法)。但是 sort
永远无法更新 *y*
以引用不同的对象,因为它没有对 *y*
本身的引用,而是对 (1 2 3)
的第一个 cons 单元格的引用.
因此,sort
returns 一个排序列表,并且应该使用它作为结果,而不是使用指向原始参数的引用。原始参数列表可能已更改:
sort
也可能 具有破坏性。
注意:破坏性排序的确切行为在 Common Lisp 中未指定
因此实现可能会出现不同的副作用。例如,参见 CLISP
实现:
[1]> (defvar *y* '(1 2 3))
*Y*
[2]> (sort *y* #'>)
(3 2 1)
[3]> *y*
(3 2 1)