Reputation: 1941
The code below implements a macro call with an implicit optional parameter--implicit because it is buried in the &rest parameter. Is there a better way to code the macro (and its supporting function)--perhaps by making the optional parameter explicit with an &optional keyword (or maybe some other way)? It is preferred that the first parameter is required, the second optional, and the numerous remaining parameters required. Also prefer to keep the macro definition simple, with the work done by the supporting function, if possible (but looking to learn more advanced approaches too):
(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)
Additional point of clarification: The slot values above are really various specifications represented as (sometimes deeply nested) lisp trees. The function install-action interprets the specs and installs their semantic content into a database.
Upvotes: 1
Views: 112
Reputation: 139251
Parameter and argument lists: style
It is useful to have explicit parameter lists. Common Lisp provides extensive support for it. But even then not every parameter list idea can be supported. As jkiiski notes in his comment, it is always helpful to have a speaking parameter list: it helps the developer, the compiler can catch some errors at compile time and Lisp can provide better debugging information.
One of the style rules: optional arguments should be at the end of the argument list. Common Lisp itself violates this at least one place (can only remember one function right now) and it is always painful and error prone.
Fix the arglist of INSTALL-ACTION:
(defun install-action (name slots &optional (duration 0))
...)
Fix the arglist of the macro, too
Use it like:
(define-action move (a b c) 1)
A list of things might better be grouped in the macro interface.
(defmacro define-action (name slots &optional duration)
...)
Or even use a keyword named arguments:
(define-action move :slots (a b c) :duration 1)
It gets longer, but readability is greatly improved.
Side question: do we need a macro DEFINE-ACTION and why?
The main reasons for such a macro are usually:
Upvotes: 3