Angenommen, ich habe einen Emacs-Lisp-Puffer, der Folgendes enthält:
(defvar foo 1)
Wenn ich eval-last-sexp
oder anrufe eval-buffer
, foo
ist gebunden an 1. Wenn ich dann diesen Puffer bearbeite an:
(defvar foo 2)
eval-last-sexp
und eval-buffer
führe diese Zeile nicht erneut aus, es foo
ist also immer noch 1.
Dies ist besonders schwierig, wenn es mehrere solcher Aussagen gibt und ich nachverfolgen muss, welche Zeilen nicht neu bewertet werden.
Ich habe nur nach einem Neustart von Emacs gesucht und dann (require 'foo)
, aber dann muss ich vorsichtig sein, um das Laden älterer .elc-Dateien zu vermeiden.
Wie kann ich absolut sicher sein, dass sich die in der aktuellen Datei definierten Variablen und Funktionen im selben Zustand befinden wie das erneute Laden von Code in einer neuen Emacs-Instanz?
quelle
makunbound
und den Code im Puffer neu auswerten.(incf emacs-major-version)
kann ich immer wieder leben. Ich bin daran interessiert, Code mit vielendefvar
Formularen zu hacken .Antworten:
Wie in anderen Antworten erläutert, wird durch die Auswertung eines
defvar
Formulars miteval-last-sexp
nicht der Standardwert zurückgesetzt.Stattdessen können Sie
eval-defun
( standardmäßig anC-M-x
in gebundenemacs-lisp-mode
) verwenden, um das gewünschte Verhalten als besondere Ausnahme zu implementieren:Wenn Sie den vollständigen Inhalt eines Puffers auswerten müssen, können Sie eine Funktion schreiben, die die Formulare der obersten Ebene nacheinander durchläuft und
eval-defun
jedes aufruft . So etwas sollte funktionieren:quelle
eval-defun
statteval-last-sexp
. Sie können sogar eine Funktion schreiben, dieeval-defun
jedes Formular im Puffer aufruft und stattdessen verwendeteval-buffer
.eval-defun
statteval-last-sexp
, sicher, aber die Schwierigkeit ist füreval-buffer
.eval-defun
jedes Formular der obersten Ebene im Puffer aufzurufen .defvar
nicht in einem befindetdefun
. Beispiel:(progn (defvar foo "bar"))
.defconst
(die immer neu bewertet werden). Kürzlich gab es einen sehr aufschlussreichen Beitrag zu diesem Thema in endlosen KlammernWie die anderen Antworten sagen, funktioniert defvar so, aber man kann es umgehen, das ist doch ein Elisp.
Sie können die Funktionsweise von defvar vorübergehend neu definieren und in dieser Zeit die Pakete neu laden, die Sie zurücksetzen möchten.
Ich habe ein Makro geschrieben, in dem während der Auswertung des Körpers defvars-Werte immer neu bewertet werden.
Beispiel Verwendung:
file_a.el
file_b.el
Hinweis: Dies sollte nur zum Zwecke der Neubewertung von Defvars verwendet werden, da Docstrings bei der Neubewertung nur ignoriert werden. Sie können das Makro so ändern, dass es auch die erneute Auswertung von Dokumentzeichenfolgen unterstützt, aber das überlasse ich Ihnen.
In Ihrem Fall könnten Sie tun
Aber wissen Sie, was diejenigen, die elisp schreiben, tun, wenn sie erwarten, dass defvar wie angegeben funktioniert. Es könnte sein, dass sie defvar verwenden, um in einer Init-Funktion den Wert zu definieren und setq zu setzen, so dass Sie möglicherweise keine Variablen erhalten, die Sie nicht beabsichtigen, aber das ist wahrscheinlich selten.
Alternative Implementierung
Mit dieser Option können Sie defvar einfach global neu definieren und steuern, ob der Wert des Symbols auf das INIT-VALUE-Argument gesetzt wird, auch wenn das Symbol durch Ändern des Werts des neuen
defvar-always-reeval-values
Symbols definiert wird.quelle
defvar
eine gute Idee ist: Es gibt verschiedene Verwendungsmöglichkeitendefvar
mit leicht unterschiedlicher Semantik. Eine Verwendung, die Ihr Makro nicht berücksichtigt, ist beispielsweise das(defvar SYMBOL)
Formular, mit dem der Byte-Compiler über das Vorhandensein einer Variablen informiert wird, ohne einen Wert festzulegen.defvar
mit einem Makro vornehmen müssen, ist es wahrscheinlich besser, dem ursprünglichendefvar
Formular ein Präfix voranzustellenmakunbound
, als es durch ein zu ersetzensetq
.Der
defvar
wird ausgewertet und tut genau das, was Sie angegeben haben. Setzt jedochdefvar
nur einen Anfangswert:Um das zu erreichen, was Sie möchten, müssen Sie entweder die Bindung der Variablen aufheben, bevor Sie sie erneut auswerten, z
oder
setq
mit den Wert einstellen, zWenn Sie hier keinen Docstring angeben müssen, können Sie den gesamten Text überspringen
defvar
.Wenn Sie dies wirklich verwenden
defvar
und automatisch aufheben möchten, müssen Sie eine Funktion schreiben, umdefvar
Aufrufe im aktuellen Puffer (oder in der Region oder im letzten Sexp usw.) zu finden. rufemakunbound
nach jedem; und dann die eigentliche Auswertung machen.quelle
eval-buffer
Wrapper gespielt, der zuerst alle Bindungen aufhebt, aber @ Francescos Antwort daraufeval-defun
ist genau das, was Sie wollen.Das folgende Makro wurde erstellt, indem
eval-defun
auf seine unterstützenden Funktionen zurückgegriffen und diese so geändert wurden, dass es nicht mehr erforderlich ist, einen Bereich eines bestimmten Puffers auszuwerten. Ich brauchte Hilfe in dem verwandten Thread. Einen Ausdruck in einen String umwandeln, und @Tobias kam zur Hilfe, um mir beizubringen, wie man die unvollständige Funktion in ein Makro umwandelt. Ich glaube nicht, dass wireval-sexp-add-defvars
vorangehen müssenelisp--eval-defun-1
, aber wenn jemand der Meinung ist, dass dies wichtig ist, lassen Sie es mich bitte wissen.quelle
Das Problem ist nicht, dass die Leitung nicht neu bewertet wird. Das Problem besteht darin, dass
defvar
eine Variable und ihr Standardwert definiert werden . Wenn eine Variable bereits vorhanden ist, wird durch Ändern ihres Standardwerts der aktuelle Wert nicht geändert. Leider denke ich, dass Sie einesetq
für jede Variable ausführen müssen, deren Wert Sie aktualisieren möchten.Dies mag ein Overkill sein, aber Sie können Ihre Datei auf diese Weise aktualisieren, wenn Sie einfach
foo
auf den neuen Standardwert aktualisieren möchten .Dazu müssen Sie jedoch den Standardwert an zwei Stellen im Code beibehalten. Sie könnten dies auch tun:
Aber wenn es eine Möglichkeit
foo
gibt, die an anderer Stelle deklariert wird, müssen Sie möglicherweise mit einigen Nebenwirkungen fertig werden.quelle
eval-defun
behandeltdefvar
, also gibt es sicher etwas ähnliches für ganze puffer?makunbound
alle im aktuellen Puffer deklarierten Variablen neu ausgewertet werden? Sie könnten Ihre eigene schreiben, aber ich glaube nicht, dass es eine Out-of-the-Box-Funktion dafür gibt. EDIT: Egal, ich verstehe, was Sie sagen. Undeval-defun
das funktioniert über den gesamten Puffer. Es sieht so aus, als ob @JordonBiondo Ihre Lösung dafür hat.defvar
Tut nichts, wenn die Variable bereits einen Wert hat (wie im Dokument angegeben:)The optional argument INITVALUE is evaluated, and used to set SYMBOL, only if SYMBOL's value is void.
. Das Problem ist nicht, dassdefvar
sich der Standardwert und nicht der aktuelle Wert ändert.(defvar a 4) (default-value 'a) (setq a 2) (default-value 'a)
; dannC-x C-e
nach demdefvar
sexp; dann(default-value 'a)
.C-x C-e
,eval-region
Und dergleichen auf einemdefvar
sexp Sie nicht den Standardwert ändern.