我正在测试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)
由于行为不一样,我想知道SBCL是否已经使用上述警告将行为更改为它认为更有可能从用户那里得到的东西?预期:
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)
答案 0 :(得分:4)
简短的回答是,这是特定于实现的行为。正如Unexpected persistence of data中所述,
来自
quote
的HyperSpec的相关文字是:如果文字对象(包括引用的话),后果是不确定的 对象进行破坏性修改。
这意味着您从这样的函数中看到的任何行为都是特定于实现的(即使某些行为在实现中比其他行为更常见)。
答案 1 :(得分:0)
您应该使用:
(let ((cons (cons 1 2)))
(defun nonliteral-cons ()
(incf (cdr cons))
cons))