3 回答

TA貢獻(xiàn)2051條經(jīng)驗(yàn) 獲得超10個(gè)贊
你在做這樣的事情:
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
引用的數(shù)據(jù)是文字?jǐn)?shù)據(jù); 它只有一個(gè)副本,修改它的后果是不確定的。上面的行為很常見,但你不能依賴它。有些編譯器會(huì)在您執(zhí)行此操作時(shí)發(fā)出警告。例如,在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
HyperSpec的相關(guān)文本quote是:
如果破壞性地修改文字對(duì)象(包括引用對(duì)象),則后果是不確定的。
創(chuàng)建可修改的列表,例如(list 1),不'(1)。在你遇到它之前,這是一個(gè)常見的陷阱。
在Scheme中也會(huì)發(fā)生同樣的事情,盡管對(duì)文檔的引用明顯不同。對(duì)于R 5 RS,文檔如下:
4.1.2文字表達(dá)
......如3.4節(jié)所述,使用像set-car這樣的變異程序來改變常量(即文字表達(dá)式的值)是錯(cuò)誤的!或字符串集!
3.4存儲(chǔ)模型
...在許多系統(tǒng)中,希望常量(即文字表達(dá)式的值)駐留在只讀存儲(chǔ)器中。為了表達(dá)這一點(diǎn),可以很方便地設(shè)想表示位置的每個(gè)對(duì)象都與一個(gè)標(biāo)志相關(guān)聯(lián),該標(biāo)志告訴該對(duì)象是可變的還是不可變的。在這樣的系統(tǒng)中,文字常量和symbol-> string返回的字符串是不可變對(duì)象,而本報(bào)告中列出的其他過程創(chuàng)建的所有對(duì)象都是可變的。嘗試將新值存儲(chǔ)到由不可變對(duì)象表示的位置是錯(cuò)誤的。

TA貢獻(xiàn)1757條經(jīng)驗(yàn) 獲得超8個(gè)贊
不要求發(fā)出警告。行為仍未定義。即使在某些情況下發(fā)出警告的實(shí)現(xiàn)中,我也看不到任何保證他們?cè)谒星闆r下都這樣做。你的代碼是在你編譯的文件中嗎?或者您在REPL中輸入的內(nèi)容?您可以寫信給SBCL郵件列表并詢問此具體案例。

TA貢獻(xiàn)1982條經(jīng)驗(yàn) 獲得超2個(gè)贊
另一個(gè)問題,如果我在SBCL中定義一個(gè)函數(shù):(defun set-head (x v) (rplaca x v))
,那為什么這個(gè)表達(dá)式(let ((x '(a b))) (set-head x 'z))
不會(huì)引發(fā)警告?我在SBCL 1.2.7上測(cè)試它。
添加回答
舉報(bào)