有人可以解释为什么我使用sbcl和clisp获得以下简单程序的不同结果吗?我正在做什么未被语言定义,或者是两个lisp解释器中的一个错误?
; Modify the car of the passed-in list
(defun modify (a) (setf (car a) 123))
; Create a list and print car before and after calling modify
(defun testit () (let ((a '(0)))
(print (car a))
(modify a)
(print (car a))))
(testit)
SBCL(版本1.0.51)产生:
0
0
CLISP(版本2.49)产生(我期望的):
0
123
答案 0 :(得分:2)
我同意Seth和Vsevolod的评论,因为这种行为是由于您修改了文字数据。尝试使用(list 0)
代替'(0)
。与此相关的问题相对频繁,所以我在这里引用HyperSpec。
3.7.1 Modification of Literal Objects:
如果文字对象是破坏性的,则后果是不确定的 修改。
字面意思(对象的)直接在程序中引用 而不是由程序计算;也就是说,作为数据出现在 引用表单,或者,如果对象是自我评估对象,则出现 作为未加引号的数据。 ``在形式(cons“one”'(“two”))中,表达式 “一个”,(“两个”)和“两个”是文字对象。''
请注意,通常(在许多实现中),如果您修改文字值,您将真正在代码本身中修改它们 - 编写自修改代码。您的示例代码将无法正常工作。
您在CCL中的示例代码:
CL-USER> (defun modify (a) (setf (car a) 123))
MODIFY
CL-USER> (defun testit ()
(let ((a '(0)))
(print (car a))
(modify a)
(print (car a))))
TESTIT
CL-USER> (testit)
0
123
123
CL-USER> (testit)
123
123
123
查看testit
的第二次评估,其中let
本身确实已包含修改后的值,因此第一个print
也会产生123
。
另请参阅:Lisp, cons and (number . number) difference,我在此更详细地解释了这一点,或者上面的Vsevolod评论中链接的问题。