Angenommen, ich definiere eine pufferlokale Variable foo
und ihr Standardwert ist "a":
(defvar foo "a")
(make-variable-buffer-local 'foo)
(default-value 'foo) ;; => "a"
Unmittelbar danach führe ich den folgenden Code aus:
(let ((foo "b"))
(with-temp-buffer
(message "foo: %s" foo))) ;; => "b"
Das Ergebnis ist "b", was der Wert ist, den ich eingestellt habe let
.
Wenn ich setq
nun die Variable setze, führe genau den gleichen Code wie zuvor erneut aus:
(setq foo "c") ;; => "c"
(let ((foo "b"))
(with-temp-buffer
(message "foo: %s" foo))) ;; => "a"
Das Ergebnis ist "a", was jetzt der Standardwert ist.
Die Frage : Für einen temporären Puffer wird der Standardwert von foo
erst festgelegt, wenn ich ihn verwende setq
. Und solange ich nicht verwende setq
, kann ich let
den Standardwert in anderen Puffern ändern?
EDIT : Wie @npostavs sagte, ist dies das, was make-varible-buffer-local
wirklich bedeutet. Wenn ich make-variable-buffer-local
mich selbst benutze , kann ich danach immer noch benutzen setq
. Dies wird jedoch sehr schwierig für die "eingebauten" pufferlokalen Variablen wie case-fold-search
. wenn ich als Paketautor, bindet case-fold-search
an nil
in den äußeren let
, und ich mag den Standardwert verwenden , in der (es kann oder auch nicht vom Benutzer eingestellt werden) with-temp-buffer
, muß ich verwenden , setq
bevor with-temp-buffer
Sie sicher , dass der Standardwert tatsächlich zu machen ist Wird verwendet, falls der Benutzer dies nicht setq
in sich hat init.el
. Für pufferlokale Variablen bedeutet dies wahrscheinlich, dass setq
es immer sicherer ist, als let
wenn wir den Wert festlegen möchten. Ich frage mich, ob das Design oder die Dokumentation verbessert werden könnten.
quelle
with-temp-buffer
(anstatt davor) legen , hilft das irgendetwas?with-temp-buffer
ist ein Makro und verhält sich etwas anders als eine Standardfunktion. ZB(with-temp-buffer (let ((foo "b")) (message "foo: %s" foo)))
with-temp-buffer
(das heißt, keine Makros). Ich denke, es ist eher ein spezifisches Verhalten für pufferlokale Variablen.Antworten:
In diesem Fall würde ich empfehlen
Das Wichtigste dabei ist, dass
make-variable-buffer-local
eine Variable nicht pufferlokal ist! Es sorgt erst dafür, dass es nach dem Festlegen pufferlokal wird . Vielleicht möchten Siemake-local-variable
stattdessen verwenden.Das zweite, was zu beachten ist, ist die Interaktion
let
mit pufferlokalen Variablen von(elisp) Intro to Buffer-Local
:Im ersten Fall binden Sie also den globalen Wert an
"b"
und dieser wird im temporären Puffer angezeigt. Im zweiten Fall, nachdem Sie den lokalen Wert*scratch*
auf festgelegt haben"c"
, binden Sie den lokalen Wert an"b"
, aber andere Puffer sehen immer noch den globalen Wert von"a"
.quelle
Make VARIABLE become buffer-local whenever it is set.
. Ich dachte, es heißt, wann immer wir den Wert setzen, wird nur der pufferlokale Wert gesetzt. Um ein solches Problem zu vermeiden, sollten wir es wahrscheinlich immersetq
sofort danach verwendenmake-variable-buffer-local
?case-fold-search
undfill-column
. Emacs selbst setzt sie nicht, nachdem es diese pufferlokalen Variablen definiert hat, und der Benutzer muss sie setzen, damit sie wirklich pufferlokal sind. Ist dieses Design beabsichtigt? Ich glaube nicht, dass die meisten Leute sich dessen bewusst sind.make-local-variable
odersetq
wenn er sagt, dass diese Variable pufferlokal ist. Aber vielleicht ist das eine andere Frage bezüglich des Designs.make-local-variable
wenn ich sehe, dass die Variable bereits "buffer-local" aus dem Handbuch ist. Ich würde erwarten, dass daslet
die pufferlokale Kopie binden könnte. Dies ist jedoch möglicherweise besser geeignet, um in Emacs-devel gefragt zu werden.Wie bei Ihrer vorgeschlagenen Lösung können wir diese an eine beliebige Variable im Inneren binden und dann nach Belieben
let
ändern, während wir im Inneren bleibenlet
, bevor wir zum ursprünglichen Wert zurückkehren.Das Problem tritt beim Ändern des Puffers im Inneren auf.
let
Aufgrund des dynamischen Bereichs wird der Wert lokaler Variablen auch im Inneren nicht in den neuen Puffer übertragenlexical-let
.Hier ist eine Funktion, die nach diesem Problem sucht und auch den Standardwert festlegt und zurücksetzt, der von einem temporären Puffer verwendet wird:
dann
und "xyz" erscheinen im
*Messages*
Puffer.Andere lokale Variablen, die in diesem Zusammenhang in den Sinn kommen, sind
default-directory
unduniquify-managed
...Kurz gesagt, Sie können eine Funktion wie diese definieren und im Inneren verwenden
let
. Sparen Sie sich also den Aufwand, zu überprüfen, ob die Variable (Symbol) lokal ist oder nicht:quelle