davypough
davypough

Reputation: 1941

Specifying optional parameters out of order

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

Answers (1)

Rainer Joswig
Rainer Joswig

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:

  • less quoting
  • special syntax
  • compile-time side-effects
  • expansion into other macro calls

Upvotes: 3

Related Questions