Unexpected persistence of data [duplicate]
Are you doing something like this:
CL-USER> (defun foo ()
(let ((value '(1))) ; '(1) is literal data
(incf (car value))))
FOO
CL-USER> (foo)
2
CL-USER> (foo)
3
CL-USER> (foo)
4
CL-USER> (foo)
5
Quoted data is literal data; there's only one copy of it, and the consequences of modifying it are undefined. The behavior above is common, but you can't depend on it. Some compilers will give a warning when you do this. E.g., in SBCL:
CL-USER> (defun foo ()
(let ((value '(1)))
(incf (car value))))
; in: DEFUN FOO
; (INCF (CAR VALUE))
; --> LET*
; ==>
; (SB-KERNEL:%RPLACA #:TMP1 #:NEW0)
;
; caught WARNING:
; Destructive function SB-KERNEL:%RPLACA called on constant data.
; See also:
; The ANSI Standard, Special Operator QUOTE
; The ANSI Standard, Section 3.2.2.3
;
; compilation unit finished
; caught 1 WARNING condition
FOO
The relevant text from the HyperSpec on quote
is:
The consequences are undefined if literal objects (including quoted objects) are destructively modified.
Create modifiable lists with, e.g., (list 1)
, not '(1)
. This is a common pitfall until you've encountered it. There are some other questions on StackOverflow that mention this issue. A very specific one is
- Why does this function return a different value every time?
but there are a bunch, too:
- LISP: Why doesn't mapcan accept my list give as parameters? (an interesting case with a literal list inside a lambda function passed to mapcan)
- Unexpected List Duplication using Sort with Common Lisp
- LISP - Global variable keep their old value after reinitialization
- this answer to Sudoku table generator failure, lisp
- How does Lisp function remember state in this code?
- Do property lists in Common Lisp refer to some global state?
- Why does this function return a different value every time?
- Strange behavior invoking destructive Common LISP function receiving as argument a list created with quote
- Local variable keeps data from previous execution
- What is happening with this Common Lisp code?
- Unexpected persistence of data (this question)
- setf in a function does not work
- duplicating and modifying the head of a list of list, in Lisp
The same thing happens in Scheme, though the citations to the documentation are obviously different. For R5RS, the documentation is the following:
4.1.2 Literal expressions
… As noted in section 3.4, it is an error to alter a constant (i.e. the value of a literal expression) using a mutation procedure like set-car! or string-set!.
3.4 Storage model
… In many systems it is desirable for constants (i.e. the values of literal expressions) to reside in read-only-memory. To express this, it is convenient to imagine that every object that denotes locations is associated with a flag telling whether that object is mutable or immutable. In such systems literal constants and the strings returned by symbol->string are immutable objects, while all objects created by the other procedures listed in this report are mutable. It is an error to attempt to store a new value into a location that is denoted by an immutable object.
There are questions about this as well:
- How could I explain this unexpected behavior of my Scheme code?
- Difference between '(()) and (cons null null)