修改作为参数传递的列表在SBCL和CLISP中给出不同的结果 [英] Modifying a list passed as a parameter gives different results in SBCL and CLISP
问题描述
有人可以解释为什么我为以下带有sbcl和clisp的简单程序得到不同的结果吗?是我在用语言定义的工作是不确定的,还是两个口齿不清的解释器之一?
Can someone explain why I get different results for the following simple program with sbcl and clisp? Is what I am doing undefined by the language, or is one of the two lisp interpreters wrong?
; 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)产生:
SBCL (version 1.0.51) produces:
0
0
CLISP(版本2.49)产生(我期望):
CLISP (version 2.49) produces (what I would expect):
0
123
推荐答案
I同意Seth和Vsevolod的评论,因为此行为是由于您对文字数据的修改而引起的。尝试使用(列表0)
代替’(0)
。与此相关的问题相对频繁地出现,因此我将引用 HyperSpec 此处。
I agree with Seth's and Vsevolod's comments in that this behavior is due to your modification of literal data. Try using (list 0)
instead of '(0)
. Questions relating to this come up relatively frequently, so I'll quote the HyperSpec here.
如果文字对象具有破坏性,则后果不明确
The consequences are undefined if literal objects are destructively modified.
文字调整。直接在程序中而不是由程序计算的
(对象的);也就是说,以
的报价形式显示为数据,或者,如果该对象是自评估对象,则以
的形式显示为未报价的数据。 以(cons one'( two)的形式,表达式
one,( two)和 two是文字对象。
literal adj. (of an object) referenced directly in a program rather than being computed by the program; that is, appearing as data in a quote form, or, if the object is a self-evaluating object, appearing as unquoted data. ``In the form (cons "one" '("two")), the expressions "one", ("two"), and "two" are literal objects.''
请注意,经常(在许多实现中)如果修改文字值,您实际上会在代码本身中对其进行修改–编写自修改代码。您的示例代码将无法正常工作。
Note that often (in many implementations), if you modify literal values, you'll really modify them in the code itself – writing self modifying code. Your example code will not work as you expect.
您在CCL中的示例代码:
Your example code in 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
。
Take a look at the second evaluation of testit
, where the let
itself really already contains the modified value, thus the first print
also yields 123
.
另请参见: Lisp,cons和(number.number)差异,其中我对此进行了更详细的解释,或者解释了上面Vsevolod的评论中链接的问题。
Also see: Lisp, cons and (number . number) difference, where I explained this in more detail, or the question linked in Vsevolod's comment above.
这篇关于修改作为参数传递的列表在SBCL和CLISP中给出不同的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!