macrospattern-matchingcommon-lisppractical-common-lisp

Difference between `(&rest xs)` and `xs` in defmacro formal argument list


In Practical Common Lisp's Chapter 8, Macros: Defining Your Own, we define a macro with-gensyms as follows:

(defmacro with-gensyms ((&rest names) &body body)
  `(let ,(loop for n in names collect `(,n (gensym)))
    ,@body))

What is the purpose of the (&rest names)? If we replace it with just names, the effect seems to be the same. In both cases we pass in a list of symbols to be "gensym-ed".


Solution

  • The difference:

    (&rest names) inside the arglist ((&rest names) &body body) matches only lists. When somebody is using the macro with something else, the error comes from the macro expander:

    debugger invoked on a SB-KERNEL::DEFMACRO-BOGUS-SUBLIST-ERROR:

    error while parsing arguments to DEFMACRO WITH-GENSYMS:

    bogus sublist A to satisfy lambda-list (&REST NAMES)

    names matches anything. When somebody is using the macro with not a list, then the error comes from the LOOP macro, which needs a list:

    debugger invoked on a TYPE-ERROR: The value A is not of type LIST.

    Thus you get a better and earlier error.