Ich bin mir nicht ganz sicher, welche Variationen von pufferlokalen Variablen es gibt, selbst nachdem ich alle Dokumente und eine Reihe von Beiträgen hier auf SX gelesen habe.
Hier ist eine Zusammenfassung meines Verständnisses:
(defvar foo ..)
deklariert eine dynamische Variable für die Datei. Die Variable ist jedoch (1) anderen Dateien nur bekannt, wenn sie auch eine defvar
Anweisung enthält, und (2) der Gültigkeitsbereich der Variablen ist global und nicht lokal gepuffert.
(make-variable-buffer-local foo)
nachdem das defvar
oben Gesagte dem Compiler und allen anderen mitgeteilt hat, dass die Variable foo überall dort als pufferlokal zu behandeln ist, wo sie gesetzt ist, wenn sie gesetzt ist. Dieses Muster eignet sich also gut zum Deklarieren einer pufferlokalen Variablen, bei der beide Anweisungen in der Datei hintereinander abgelegt werden.
(defvar xxx ...) ;declare xxx with global scope
(make-variable-buffer-local 'xxx) ;but now make it buffer-local everywhere
Der Einfachheit halber kann das (defvar-local xxx ...)
Formular anstelle der beiden obigen Zeilen als eine Zeile verwendet werden:
(defvar-local xxx ...) ;make xxx buffer local everywhere
Einmal wie oben deklariert, kann die Variable xxx wie jede andere Variable in setq-Anweisungen verwendet werden.
Wenn ich nur eine einzelne Instanz einer pufferlokalen Variablen haben möchte, die bereits eine globale dynamische Variable ist, würde ich die folgenden Deklarationen verwenden. Die erste deklariert die dynamische Variable mit globalem Gültigkeitsbereich und die zweite Anweisung erstellt nur eine Instanz einer pufferlokalen Version dieser Variablen im aktuellen Puffer:
(defvar xxx ...) ;declare xxx with global scope
(make-local-variable 'xxx) ;make xxx local in this buffer only
Nun zu meinen expliziten Fragen (alle oben genannten waren implizite Fragen, ob mein Verständnis korrekt ist).
Wenn ich den Wert von Variablen einstelle, kann ich setq
oder verwenden
setq-local
. Wann sollte setq-local
verwendet werden? Warum?
Was passiert, wenn ich setq-local
pufferlokale oder nicht pufferlokale Variablen verwende?
Wird setq-local
für eine defvar-local
deklarierte Variable benötigt?
Verwandelt sich setq-local
eine normal defvar
deklarierte Variable in eine pufferlokale Variable? (Mit anderen Worten, ist das setq-local
irgendwie das Äquivalent einer (make-variable-local xxx)
Erklärung?
quelle
(setq-local VAR VALUE)
ist nur eine Abkürzung für(set (make-local-variable VAR) VALUE)
, was eine verbreitete Redewendung war (und immer noch ist).Antworten:
Die meisten Ihrer Annahmen sind nah. Ich werde später einige erwähnen. Aber zuerst die Hauptfrage.
Das Formular
setq-local
ist lediglich eine Annehmlichkeit, es ist dasselbe wie das Ausführen,make-local-variable
gefolgt vonsetq
. Wenn Sie sich C-h f setq-localdie Dokumentation angesehen und zur Quelle durchgeklickt haben, haben Sie dies möglicherweise gesehen. So habe ich meinen ersten Eindruck bestätigt. Der Code ist jedoch etwas unklar, da er Dinge wie die Tatsache optimiert, dassmake-local-variable
die Variable selbst zurückgegeben wird. Mithilfe vonsetq-local
wird die Lokalität in einigen Codes hervorgehoben, sodass andere wissen, dass der Code nicht mit dem globalen Wert der Variablen abgespielt werden kann. Sie müssen es nicht verwenden, um auf lokale Variablen zuzugreifen. Jede Variable kann pufferlokal gemacht werden und wirkt sich auf den gesamten Code aus, der die Variable berührt (es sei denn, es wird alles unternommen, um die globale Kopie mitsetq-default
oder ähnlichem zu erhalten).Das ist die primäre Antwort. Nun, es gibt einige Dinge in Ihrem Hintergrund, die ein wenig anders sind. Da Sie danach gefragt haben, werde ich einige Dinge ansprechen.
Die erste ist "anderen Dateien nicht bekannt". Das stimmt nicht wirklich. Jeder Code kann auf jede globale Variable verweisen (deshalb werden sie "global" genannt), ohne das
defvar
(und C-h f defvarsagt es). Tatsächlich sollte es für jede globale Variable nur ein Hauptverzeichnisdefvar
(mit Dokumentzeichenfolge und Standardwert) geben. Eindefvar
mit nur dem Variablennamen kann verwendet werden, um eine Byte-Compiler-Warnung zu unterdrücken. Emacs verwendet nur den Wert des ersten, den es sieht¹, und den Docstring des letzten. Wenn es mehreredefvar
s mit value / docstring gibt, können sie für die Leser des Codes verwirrend sein. Und die Reihenfolge des Ladens von Dateien spielt eine Rolle.Einige Variablen werden soll nur als Puffer-local verwendet werden und das sind diejenigen , die Verwendung
defvar-local
(oder die zweiteiligedefvar
/make-variable-buffer-local
die es kurz für ist, vor allem bei älteren Code , bevor die Kurzform hinzugefügt wurde). Dies macht es in allen Puffern pufferlokal. Für einige Variablen ist ihre primäre Verwendung nicht pufferlokal, aber aus irgendeinem Grund möchten Sie möglicherweise, dass ein Puffer einen anderen Wert hat. Das ist, wenn Sie verwendenmake-local-variable
, in der Regel in einigen Puffer-Setup-Code fast nie direkt nach einemdefvar
.Und im Allgemeinen haben die
defvar
Formen zwei Zwecke . Eine besteht darin, eine Dokumentation zu haben, damit C-h vandere wissen, wozu die Variable dient. Die zweite besteht darin, einen "Standard" -Wert zu deklarieren, damit die Variable immer gesetzt wird. Die Deklaration des Standardwerts wirkt sich nur auf die globale (oder Standard-) Instanz einer Variablen aus und wird nur verwendet, wenn für diese Instanz noch kein Wert festgelegt wurde. Das heißt, wenn Siesetq
eine Variable und dann die Datei mitdefvar
(z. B. durch einrequire
), wird die Defvar den Wert nicht ändern.¹ Genauer gesagt:
defvar
Ändert den Wert der Variablen nicht, wenn er bereits festgelegt ist (es wird jedoch die Dokumentzeichenfolge festgelegt). Dies ist so gemeint, dass die Init-Datei des Benutzers dies tun kann,(setq some-variable)
bevor ein Paket geladen wird, um den Standardwert des Pakets zu überschreiben.quelle
set-local
die den Lesern sagt, dass eine lokale Variable gesetzt wird. Alles, was ich tun kann, um die Lesbarkeit meines Codes zu verbessern, ist gut! PS. Ich werde versuchen, öfter zur Quelle durchzuklicken. Bei meinem derzeitigen Entwicklungsstand kommt es oft nicht wirklich auf die Semantik an ... :-)defvar
für jede globale Variable“ ist nicht ganz richtig - es gibt Situationen , in denen(defvar VARNAME)
ohne einen Wert sollte unabhängig von der richtigen Definition deklariert werden (mit Anfangswert und im Idealfall eines docstring) davon VARNAME.setq-local
unddefvar-local
nur in Emacs 24.3 eingeführt wurden.(defvar varname)
deklariert werden sollte ? Ich denke, das hat Drew in einem anderen Thread vorgeschlagen, als ich gefragt habe, wie ich Warnungen zu freien Variablen in meinen Dateien für Globals entfernen kann, die ich an anderer Stelle deklariert hatte. Ich mache das jetzt. Ist das die Situation, von der Sie sprechen?C-h i g (elisp) Warning Tips
). Die andere ist für Bibliotheken gedacht, die die lexikalische Bindung verwenden, um (falls erforderlich) sicherzustellen, dass eine Variable dynamisch und nicht lexikalisch gebunden ist.