Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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".

like image 779
Tianxiang Xiong Avatar asked Dec 30 '15 09:12

Tianxiang Xiong


1 Answers

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.

like image 151
Rainer Joswig Avatar answered Sep 28 '22 06:09

Rainer Joswig