Modifying a list passed as a parameter gives diffe

2019-02-28 01:30发布

问题:

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 (version 1.0.51) produces:

0 
0 

CLISP (version 2.49) produces (what I would expect):

0 
123 

回答1:

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 Modification of Literal Objects:

The consequences are undefined if literal objects are destructively modified.

The definition of "literal":

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.

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

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.

Also see: Lisp, cons and (number . number) difference, where I explained this in more detail, or the question linked in Vsevolod's comment above.



标签: common-lisp