Search code examples
common-lisp

Macro : How to output a comma in a backquoted generated code?


I have a macro of the form:

;; Macro which does a sort of defun for instance, with some other stuff.
(defmacro def2 (name (&rest args) &body body)
  `(defun ,(intern (string-upcase name)) (,@args)
     ,@body))

And I want to generate lots of def2 :

(defmacro defdefs ()
  `(progn
     ,@(loop for name in '("name1" "name2" "name3")
         collect `(def2 ,name (&rest args)
            (print ,@args))))) ; <---- HERE.

I want to refer to the args in the def2 form, but if I write ,@args it will refer to a variable (not defined) in defdefs macro. I have thought to use something like macro-function and apply but is there a better way to tell defdefs that I want to output this list : (print ,@args) without evaluating the ,@args part during macroexpansion?

I have tried to play with quotes, double quotes, backquotes and double backquotes but I cannot find a solution...

Thank you in advance.


Solution

  • CL-USER 33 > (defmacro def2 (name (&rest args) &body body)
                   `(defun ,(intern (string-upcase name)) (,@args)
                      ,@body))
    DEF2
    
    CL-USER 34 > (defmacro defdefs ()
                   `(progn
                      ,@(loop for name in '("name1" "name2" "name3")
                              collect `(def2 ,name (&rest args)
                                         (print args)))))
    DEFDEFS
    
    CL-USER 35 > (pprint (macroexpand '(defdefs)))
    
    (PROGN
      (DEF2 "name1" (&REST ARGS) (PRINT ARGS))
      (DEF2 "name2" (&REST ARGS) (PRINT ARGS))
      (DEF2 "name3" (&REST ARGS) (PRINT ARGS)))
    
    CL-USER 36 > (pprint (macroexpand-1 '(DEF2 "name1" (&REST ARGS) (PRINT ARGS))))
    
    (DEFUN NAME1 (&REST ARGS)
      (PRINT ARGS))