2011-01-08 4 views
5

Der Code hat unter z als lokale Variable, aber es verhält sich, als ob es sich um eine globale ist:Bezeichnen Eigenschaftenlisten in Common Lisp einen globalen Status?

(defun foo (m) 
    (let ((z '(stuff nil))) 
    (push m (getf z 'stuff)) 
    (print z))) 

(foo 1) 
(foo 2) 
(foo 3) 

ich die Ausgabe

(STUFF (1)) 
(STUFF (2)) 
(STUFF (3)) 
T 

aber wenn es mit SBCL ich laufen erwarten siehe

(STUFF (1)) 
(STUFF (2 1)) 
(STUFF (3 2 1)) 
T 

Warum ist das der Fall? Ist dieses Verhalten Eigenschaftslisten eigen?

+0

Mögliches Duplikat [Unexpected Persistenz von Daten] (http://stackoverflow.com/questions/18790192/unerwartete Persistenz von Daten) –

Antwort

6

In foo ist z an den literalen Ausdruck '(stuff nil) gebunden. Die Funktion ändert destruktiv z und ändert damit den Wert des Literals destruktiv. Wie sich LISP in solchen Situationen verhält, ist implementierungsabhängig. Einige Implementierungen werden den literalen Wert gehorsam ändern (wie in Ihrem Fall). Andere Implementierungen platzieren Literale in schreibgeschützten Speicherorten und schlagen fehl, wenn Sie versuchen, diese Literale zu ändern.

das gewünschte Verhalten zu erhalten, COPY-LIST verwenden, um eine Kopie der wörtlichen zu machen, die sicher geändert werden können:

(defun foo (m) 
    (let ((z (copy-list '(stuff nil)))) 
    (push m (getf z 'stuff)) 
    (print z))) 
+7

Ich denke, der idiomatische Weg wäre, 'LIST' zu verwenden, wie in' (let ((z (list 'stuff nil)))) – Ken