修改作为参数传递的列表在SBCL和CLISP中给出不同的结果 [英] Modifying a list passed as a parameter gives different results in SBCL and CLISP

查看:80
本文介绍了修改作为参数传递的列表在SBCL和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.

3.7.1文字对象的修改


如果文字对象具有破坏性,则后果不明确

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆