问题
I'm testing out the code in this interesting answer.
CL-USER> (defun literal-cons ()
(let ((cons '(1 . 2)))
(incf (cdr cons))
cons))
; in: DEFUN LITERAL-CONS
; (INCF (CDR CONS))
; --> LET*
; ==>
; (SB-KERNEL:%RPLACD #:CONS1 #:NEW0)
;
; caught WARNING:
; Destructive function SB-KERNEL:%RPLACD 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
LITERAL-CONS
CL-USER> (literal-cons)
(1 . 3)
CL-USER> (literal-cons)
(1 . 3)
CL-USER> (literal-cons)
(1 . 3)
As the behavior is not the same, I am wondering if SBCL has used the mentioned warning to change the behavior to something it thinks is more likely expected from the user? Expected:
TEST> (defun literal-cons ()
(let ((cons '(1 . 2)))
(incf (cdr cons))
cons))
LITERAL-CONS
TEST> (literal-cons)
(1 . 3)
TEST> (literal-cons)
(1 . 4)
TEST> (literal-cons)
(1 . 5)
回答1:
The short answer is that yes, this is implementation specific behavior. As discussed in Unexpected persistence of data,
The relevant text from the HyperSpec on quote is:
The consequences are undefined if literal objects (including quoted objects) are destructively modified.
This means that any behavior you see from such a function is implementation specific (even if certain behaviors are more common among implementations than others).
回答2:
You should use:
(let ((cons (cons 1 2)))
(defun nonliteral-cons ()
(incf (cdr cons))
cons))
来源:https://stackoverflow.com/questions/20342793/is-this-an-implementation-specific-behavior-for-literal-cons