Ich bringe mir etwas mehr Elisp bei und bin auf folgendes Problem gestoßen:
Wenn ich eine Listenvariable zurücksetzen möchte, wird sie nach der ersten Auswertung nicht aktualisiert. Hier ist ein Beispielcode:
(defun initilize ()
(setq example '(3)))
(defun modify ()
(initilize)
(message "%S" example)
(setcar example 2))
; M-x eval-buffer RET
(modify) ; message --> (3)
(modify) ; message --> (2)
(modify) ; message --> (2)
Ich interessiere mich für zwei Dinge. Das erste ist, mehr darüber zu erfahren, was "unter der Haube" passiert. Warum funktioniert es also beim ersten Mal und schlägt bei nachfolgenden Anrufen fehl?
Die zweite und praktischere Frage ist, wie die Liste richtig neu initialisiert werden kann, oder gibt es eine andere übliche Methode, um so etwas zu tun?
Eine Problemumgehung, die ich selbst gefunden habe, besteht darin, eine zitierte Liste zu verwenden und den Inhalt folgendermaßen zu bewerten:
(setq example `(,3))
example
es nie als Variable deklariert wurde, also so tun setq
muss, als ob es eine neue Variable deklariert, aber später, wenn Sie initialize
erneut aufrufen, wird eine neue Variable erstellt, während modify
die alte gespeichert wird ... In jedem Fall ist dies kein erwartetes Verhalten. Die Verwendung von setq
etwas, das zuvor nicht als Variable eingeführt wurde, kann jedoch genauso gut undefiniert sein.
'(3)
wird als wörtlicher Wert behandelt. (setcar '(3) 2)
Wenn Sie also einmal , wann immer Sie dies tun (defvar foo '(3))
oder (let ((foo '(3)))
so weiter, erhalten Sie wahrscheinlich einen Wert von foo
gleich '(2)
. Ich sage "wahrscheinlich", weil dieses Verhalten nicht garantiert ist. Es ist eine Art Optimierung, die der Interpreter immer dann durchführt, wenn er Lust hat, etwas, das als Eliminierung von Konstanten-Subausdrücken bekannt ist (ein besonderer Fall von). Was abo-abo schrieb, ist also nicht genau der Grund. Es ist eher so, als würde man ein String-Literal in C ändern (was normalerweise eine Warnung generiert).
'(some list)
zu sein ,eq
um'(some list)
- je .Es ist in der Regel keine Garantie in Lisp , dass Code, der sichtbar zitiert eine Liste zurückgibt neue Listenstruktur jedes Mal. In einigen Lisp-Implementierungen kann dies der Fall sein oder manchmal. Bei anderen ist dies niemals der Fall. Ihr Code sollte ohnehin nicht von einem solchen Verhalten der Implementierung abhängen. Wenn Sie eine neue Listenstruktur wünschen, verwenden Sielist
odercons
oder eine gleichwertige.