Ich arbeite an der Optimierung meiner Emacs-Konfiguration, in der ich dynamisch interaktive Funktionen für alle Themen erstellen kann, die ich in einer Liste habe.
Unten finden Sie eine vereinfachte Version des Konstrukts, mit dem ich arbeiten möchte.
;; List containing names of functions that I want to create
(setq my/defun-list '(zz-abc
zz-def
zz-ghi))
;; Elisp macro to create an interactive defun whose name
;; is passed as the macro argument
(defmacro my/create-defun (defun-name)
`(defun ,defun-name ()
(interactive)
(let ((fn-name (symbol-name ',defun-name)))
(message "Testing creation of function %s" fn-name))))
;; Loop to call the above macro for each element in the list
;; DOES *NOT* WORK
(dolist (name my/defun-list)
(my/create-defun name))
Aber wenn ich die Schleife manuell abwickle, funktioniert es:
;; WORKS
(my/create-defun zz-abc)
(my/create-defun zz-def)
(my/create-defun zz-ghi)
Aber das Folgende funktioniert nicht, wenn ich die Symbolnamen übergebe (was wahrscheinlich passiert, wenn sich die Schleife von selbst abwickelt). Beachten Sie die Anführungszeichen vor den Makroargumenten.
;; DOES *NOT* WORK
(my/create-defun 'zz-abc)
(my/create-defun 'zz-def)
(my/create-defun 'zz-ghi)
Aktualisieren
Dank der Hilfe von @wvxvw habe ich es endlich geschafft !
Wie @wvxvw vorschlägt, werde ich keine Batch-generierenden Defuns für jeden Anwendungsfall erstellen. Dies war ein spezieller Anwendungsfall, bei dem XYZ
ich für ein Thema mit dem Namen einen Defun generieren möchte load-theme/XYZ
, der die Aufgabe erfüllt
- Deaktivieren aller anderen Themen, die möglicherweise aktiv sind
- Fordern
load-theme
nachXYZ
- Weitere benutzerdefinierte Aufgaben im Zusammenhang mit diesem Thema ausführen; Ich übergebe die benutzerdefinierten Einstellungen für jedes Thema über die
my/themes
Liste.
quelle
defuns
in einprogn
.progn
darf ein Formular der obersten Ebene sein (in dem Sinne, dass alles, was für Formulare der obersten Ebene gilt, auch für den Inhalt von giltprogn
). Aber ich würde die Gründe für die Erstellung von Funktionen so in Frage stellen: Warum nicht beispielsweise eine Has-Tabelle mit Lambdas als Werten?cons
es, aber ich plane, diese in Listen mit benutzerdefinierten Eigenschaften für jedes Thema zu konvertieren.(my/create-defun name)
dreimal aufgerufen , also sollten Sie einename
dreimal definierte Funktion definieren .Antworten:
Hier ist ein Erklärungsversuch und ein Vorschlag.
Versuchen wir nun, dies zu beheben:
Beispiel mit dem Lesen von Funktionsnamen aus einer Variablen
Das Problem war konzeptioneller Art: Makros dienen zum Generieren von Code, wenn die Umgebung ihn lesen möchte. Wenn Sie den Code selbst ausführen (als Benutzer Ihres Programms), ist dies bereits zu spät (die Umgebung sollte bis dahin wissen, was das Programm ist).
Eine Randnotiz: Ich würde davon abraten, mehrere zusammenzufassen
defuns
. Der Grund ist, dass das Debuggen dadurch viel komplizierter wird. Die geringe Redundanz, die Sie bei wiederholten Definitionen haben, zahlt sich während der Wartungsphase sehr gut aus (und die Wartung ist normalerweise die längste Phase in der Programmlebensdauer).quelle
mapcar
mit Alisten verwende. Dies scheint mit meinem tatsächlichen Anwendungsfall nicht zu funktionieren. Ich werde mich so schnell wie möglich damit befassen.(mapcar (lambda (x) (message "argument: %s" x)) some-alist)
, um zu sehen, was das Argument ist, das Sie bekommen, und von dort aus arbeiten. Wenn das eine assoziative Liste ist, würde ich mir vorstellen, dass die Ausgabe so etwas wie istargument: (foo . bar)
, dann könnten Siefoo
mitcar
undbar
mitcdr
Funktionen darauf zugreifen .nth
fn anstelle voncar
und verwendet habecadr
), aber dassequencep
Einchecken istmapcar
fehlgeschlagen. Ich gab eine Liste als Eingabe an, aber Mapcar glaubte immer noch nicht, dass dies eine Sequenz war. Wenn ich das tat(sequencep my-alist)
, war das nicht Null. Also bin ich verwirrt. Ich muss das noch debuggen.my-alist
warnil
oder du hast Anführungszeichen vergessen (oder hinzugefügt), so dass diesmy-alist
entweder ein Symbol war oder noch weiter bewertet wurde, um etwas anderes zu sein. Sie möchten Ihre Frage wahrscheinlich mit dem neuen Code erweitern, um die Beantwortung zu vereinfachen.Nicht gerade defuns, aber warum nicht? : P.
quelle
Ich habe folgendes in meinem Init:
Es ist vielleicht etwas komplexer als nötig (insbesondere diese zusätzliche Auswertung), aber es ermöglicht mir, die Defuns zu generieren, die ich für diese Eigenschaften benötige (und Docstrings mit den richtigen Informationen in die Strings aufzunehmen).
quelle