Der folgende Code implementiert einen Makroaufruf mit einem impliziten optionalen Parameter - implizit, da er im & Restparameter eingebettet ist. Gibt es eine bessere Möglichkeit, das Makro (und seine unterstützende Funktion) zu codieren - vielleicht indem der optionale Parameter explizit mit einem optionalen Schlüsselwort & (oder auf eine andere Weise) angegeben wird? Es ist bevorzugt, dass der erste Parameter erforderlich ist, der zweite optional ist und die zahlreichen verbleibenden Parameter erforderlich sind. Auch bevorzugt die Makrodefinition einfach, mit der Arbeit durch die unterstützende Funktion getan zu halten, wenn möglich (aber auf der Suche fortgeschrittenere Ansätze zu lernen):Angeben optionaler Parameter außerhalb der Reihenfolge
(defstruct action
name duration slot1 slot2 slot3)
(defmacro define-action (name &rest rest)
`(install-action ',name ',rest))
(defun install-action (name &rest rest)
(let* ((slots (first rest))
(duration (if (numberp (first slots))
(prog1 (first slots)
(setf slots (cdr slots)))
0))
(action (make-action :name name :duration duration
:slot1 (first slots) :slot2 (second slots)
:slot3 (third slots))))
(print action)))
(define-action move a b c) ;first example no duration
(define-action move 1 a b c) ;second example with duration=1
#S(ACTION :NAME MOVE :DURATION 0 :SLOT1 A :SLOT2 B :SLOT3 C)
#S(ACTION :NAME MOVE :DURATION 1 :SLOT1 A :SLOT2 B :SLOT3 C)
Zusätzliche Klarstellung: Die Slot-Werte oben sind wirklich verschiedene Spezifikationen, die als (manchmal tief verschachtelte) Lisp-Bäume dargestellt werden. Die Funktion install-action interpretiert die Spezifikationen und installiert ihren semantischen Inhalt in einer Datenbank.
zitieren Wenn die restlichen Parameter benötigt werden, wäre es besser, sie nur als reguläre benannte Parameter zu verwenden.Auf diese Weise können Benutzer des Makros aus der Lambda-Liste sehen, was sie ihm geben sollen, anstatt raten zu müssen (/ die Dokumente lesen). Die optionale Dauer könnte ein Schlüsselwort/optionaler Parameter am Ende sein. Oder Sie könnten etwas wie '(Name (und optional (Dauer 0)) slot1 slot2 slot3) für das Makro haben. – jkiiski
Ich würde es vorziehen, Ihre Lösung zu verwenden, wenn ich es zur Arbeit bringen kann. (Wusste nicht, benötigt/optional könnte so gemischt werden.) Wie erhalten Sie (defacroc define-action (Name (und optional (Dauer 0)) slot1 slot2 slot3) '(Installation-Aktion ', Name', Dauer ', slot1', slot2 ', slot3)) Makroexpand richtig? (ps: Wie zeichnet man eine bevorzugte Lösung in Stackoverflow für einen Kommentar auf?) – davypough
Das sollte funktionieren: '(macroexpand '(define-action foo (3) abc)) =>' (INSTALL-ACTION' FOO '3' A "B" C) ". Denken Sie daran, dass Sie um die Dauer herum Parens setzen müssen (oder leere Parens, wenn Sie keine Dauer haben). – jkiiski