有人可以解释为什么我得到了下面的程序与SBCL和CLISP不同的结果? 是我在做什么用的语言未定义,或者是两个口齿不清翻译错了吗?
; 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
我与Seth的和梅耶在这一评论这种行为是同意因您的文字数据的修改。 尝试使用(list 0)
而不是'(0)
关于这个问题上来比较频繁,所以我会引用HyperSpec这里。
3.7.1变形例文字对象 :
如果文字对象破坏性修改的后果是不确定的。
在的“文字”的定义 :
文字形容词。 直接在一个程序所引用,而不是由程序被计算(一个对象的); 即,在一个报价表显示为数据,或者,如果该对象是一个自我评估对象,显示为无引号数据。 ``在形式(利弊“一”“(‘二’)),表述‘一个’(‘2’),和‘二’是文字对象。””
需要注意的是经常(在许多实现),如果修改文字值,你会真正改变他们的代码本身-写自修改代码 。 因为你希望你的示例代码将无法正常工作。
在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的,缺点和(号数)的区别 ,在这里我更详细,或在梅耶的评论链接上面的问题说明这一点。
文章来源: Modifying a list passed as a parameter gives different results in SBCL and CLISP