Ich bin an das veraltete Elisp-Makro gewöhnt flet
und wurde aufgefordert, zu zu wechseln cl-flet
. Doch auf diese Änderung gestoppt einige meiner elisp Programme machen Arbeit und ich erkennen , der Grund , dass, im Gegensatz zu flet
, cl-flet
nicht für rekursive Funktionen erlaubt. Beispiel: Definieren Sie die folgende Funktion
(defun show-problem-in-action (x)
(cl-flet (
(factorial (n)
(if (= n 0)
1
(* n (factorial (- n 1))) )))
(factorial x) ))
man bekommt keinen Fehler durch Aufrufen
(show-problem-in-action 0)
Ausgabe: 1
weil sich die Funktion "cl-flet-defined" factorial
nicht selbst aufruft, wenn "x = 0". jedoch
(show-problem-in-action 5)
erzeugt den Fehler void-function factorial
.
Auf der anderen Seite cl-flet
durch das veraltete Makro ersetzen flet
, wie unten
(defun no-problem-with-deprecated-macro (x)
(flet (
(factorial (n)
(if (= n 0)
1
(* n (factorial (- n 1))) )))
(factorial x) ))
ermöglicht rekursiven Aufruf:
(no-problem-with-deprecated-macro 5)
Ausgabe: 120
Wenn cl-flet
es nicht funktioniert, was wäre meine beste Alternative, um es zu ersetzen flet
und trotzdem Funktionen rekursiv aufrufen zu können?
quelle
flet
undcl-flet
nicht die mangelnde Unterstützung für die Rekursion, sondern die Tatsache, dass Funktionsdefinitionenflet
mit dynamischem Gültigkeitsbereich bereitgestellt werden, während Funktionsdefinitionencl-flet
mit lexikalischem Gültigkeitsbereich bereitgestellt werden. Dynamisches Scoping bietet Unterstützung für die Rekursion, da es sich intern auf eine Indirektion stützt.Antworten:
Verwenden Sie
cl-labels
anstelle voncl-flet
. Erklärungen finden Sie im emacs-Handbuchquelle
C-h f cl-flet
der Tat, die sagt "Wie,cl-labels
aber die Definitionen sind nicht rekursiv."flet
undcl-labels
dass die Funktionen mit dieser Syntax definiert ist , muß über den #‘quotation bezeichnet werden, wie es zu den üblichen Single-Quote gegenüber .cl-labels
, wie @phils hervorhebt. Ich werde es gerne löschen, falls jemand denkt, dass es unnötigen Speicherplatz in diesem Forum verbraucht.