我定义了一个特殊变量* unsorted-lst *和一个在我的脚本中重置此变量的函数:
(defparameter *unsorted-lst* nil)
(defun reset-to-unsorted-list ()
(setf *unsorted-lst* '(1 3 0 22 3 1 3 299 31 5 0 3 7 96 24 44))
(format t "after reset: ~a~%" *unsorted-lst*)
)
之后我将它们复制到SBCL控制台进行测试,我做了:
* (setf *unsorted-lst* '(1 2 3))
(1 2 3)
* (reset-to-unsorted-list)
after reset: (1 3 0 22 3 1 3 299 31 5 0 3 7 96 24 44)
NIL
到目前为止一切正常。然后我做了
* (setf (second *unsorted-lst*) 100)
100
* (reset-to-unsorted-list)
after reset: (1 100 0 22 3 1 3 299 31 5 0 3 7 96 24 44)
NIL
函数中的setf似乎不起作用,第二个元素值仍为100.这真让我感到困惑。我必须直接在控制台中键入setf命令才能进行更改:
* (setf *unsorted-lst* '(1 3 0 22 3 1 3 299 31 5 0 3 7 96 24 44))
(1 3 0 22 3 1 3 299 31 5 0 3 7 96 24 44)
* *unsorted-lst*
(1 3 0 22 3 1 3 299 31 5 0 3 7 96 24 44)
现在它有效。我不知道它有什么不对?是否有一些对setf的误解?还是变量?
答案 0 :(得分:9)
您需要将变量数据设置为新的新列表,这是文字数据的副本。不要让全局变量指向函数的本地文字数据。
您正在查看的是Common Lisp程序中的未定义行为。
您在函数中使用文字数据。稍后,您可以通过更改列表的第二个元素来修改此文字数据。究竟发生了什么是未申报的。一些可能的结果:
许多实现只是更改文字数据。在这种情况下,函数的数据会发生变化。
如果希望函数重置变量值并创建非文字数据,则需要先复制文字列表。
CL-USER 30 > (defparameter *unsorted-lst* nil)
*UNSORTED-LST*
CL-USER 31 > (defun reset-to-unsorted-list ()
(setf *unsorted-lst*
(copy-list '(1 3 0 22 3 1 3 299 31 5 0 3 7 96 24 44)))
(format t "after reset: ~a~%" *unsorted-lst*))
RESET-TO-UNSORTED-LIST
CL-USER 32 > (setf *unsorted-lst* '(1 2 3))
(1 2 3)
CL-USER 33 > (reset-to-unsorted-list)
after reset: (1 3 0 22 3 1 3 299 31 5 0 3 7 96 24 44)
NIL
CL-USER 34 > (setf (second *unsorted-lst*) 100)
100
CL-USER 35 > (reset-to-unsorted-list)
after reset: (1 3 0 22 3 1 3 299 31 5 0 3 7 96 24 44)
NIL