Stellen Sie sich vor, ich habe die folgenden Dateien in meinem (lächerlichen) Paket:
Datei test1.el
:
;;; test1.el ---
;;; Code:
(defvar test-var1)
(defun test-fun1 (test)
nil)
(require 'test2 "./test2.el)
(provide 'test1)
;;; test1.el ends here
Datei test2.el
:
;;; test2.el ---
;;; Code:
(defun test-fun2 ()
(let ((test test-var1))
(test-fun1 test)))
(provide 'test2)
;;; test2.el ends here
Wenn ich dann renne:
emacs -batch -f batch-byte-compile *.el
Ich erhalte folgendes Ergebnis:
Compiling .../test1.el...
Wrote .../test1.elc
Compiling .../test2.el...
In test-fun2:
test2.el:9:15:Warning: reference to free variable `test-var1'
In end of data:
test2.el:14:1:Warning: the function `test-fun1' is not known to be defined.
Wrote .../test2.elc
Ich verstehe, warum diese Warnungen erscheinen, und ich verstehe, dass es sich nur um Warnungen handelt. Es wäre jedoch leicht, einen Tippfehler in einem Funktionsnamen zu übersehen, wenn alle Warnungen dieser Art verworfen würden.
Ich dachte irgendwie, dass das Hinzufügen einer (require 'test2)
Zeile das test2.el
Problem beheben sollte. In diesem Fall bekomme ich jedoch:
Compiling .../test1.el...
In toplevel form:
test1.el:10:1:Error: Recursive `require' for feature `test2'
Compiling .../test2.el...
In toplevel form:
test2.el:5:1:Error: Recursive `require' for feature `test1'
Das ist kryptisch, weil ich dachte, dass require
es genau darum geht, rekursives Laden zu vermeiden. Ich gehe davon aus, dass require
sich das wie load
während der Kompilierungszeit verhält .
Was ist ein guter (und sicherer) Weg, um diese Warnungen loszuwerden?
Das Handbuch gibt einen Workaround (ich poste es unten als eine Antwort, die besser als nichts ist), aber letztendlich möchte ich, dass die Lösung eher automatisch ist (ohne dass ich alle Funktionen und Variablen auflisten muss, die ich benötige jede Datei).
Die ideale Lösung wäre in Emacs eingebaut oder mit Cask versehen. Wenn es nicht existiert, werde ich natürlich nehmen, was verfügbar ist.
quelle
-mode
Funktion). Das Beispiel ist ein Spielzeugbeispiel, dessen Verwendungtest-fun2
das Problem überhaupt nicht ändern würde.test-variables
), und für diese Datei müssen keine anderen Dateien erforderlich sein.eval-when-compile
's eingeschlossen werden, und die Pakete müssen ihre Variable aufnil
am Ende der Datei setzen (da alle Dateien kompiliert sind eine einzelne Sitzung). Es hat auch den Vorteil, mir zu zeigen, warum genaues rekursives Laden komplizierter zu vermeiden ist als wiederholtes Laden.Ihr Beispiel ist komisch:
require
testen2 am Ende von test1, währendrequire
"immer" am Anfang einer Datei stehen sollte.require
es das unnötig), und OTOH Ihr test2 ruft test1-Funktionen auf, benötigt also test1, schlägt jedoch fehlrequire
.IOW, du hast dein
require
s rückwärts.quelle
test1
würde natürlich die durch definierte Funktion verwendettest2
, und das Paket würde nur durchtest1
(durch Autoload) geladen . Sollte diese Antwort nicht stattdessen ein Kommentar sein? Es wird nur darauf hingewiesen, dass mein Beispiel eher schlecht gewählt ist und ansonsten keine Antwort auf die Frage liefert.Das Handbuch schlägt das Hinzufügen
declare-function
unddefvar
Linien vor.Die resultierende
test2
Datei lautet:Dies muss jedoch für alle Funktionen und alle Variablen erfolgen, die in "übergeordneten" Dateien definiert sind.
quelle