1

有人可以解释为什么我使用 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 
4

1 回答 1

2

我同意 Seth 和 Vsevolod 的评论,因为这种行为是由于您修改了文字数据。尝试使用(list 0)而不是'(0). 与此相关的问题比较频繁,因此我将在此处引用HyperSpec

3.7.1 文字对象的修改

如果文字对象被破坏性修改,后果是不确定的。

“字面”的定义:

字面上的形容词。(对象的)在程序中直接引用而不是由程序计算;也就是说,以引用形式显示为数据,或者,如果对象是自评估对象,则显示为未引用的数据。``在 (cons "one" '("two")) 形式中,表达式 "one"、("two") 和 "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 评论中链接的问题。

于 2012-04-28T20:29:22.910 回答