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

1

9

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

Prakash answered 30/12, 2015 at 9:4 Comment(0)
G
11

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.

Guglielma answered 30/12, 2015 at 10:42 Comment(2)
So it's idiomatic to use ((&rest args)) when we expect args to be a list?Prakash
@TianxiangXiong: wouldn't you want to use the more specific construct?Guglielma

© 2022 - 2024 — McMap. All rights reserved.