修改作为参数传递的列表给出SBCL和CLISP不同的结果(Modifying a list pass

2019-07-29 05:01发布

有人可以解释为什么我得到了下面的程序与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 

Answer 1:

我与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
标签: common-lisp