This is a read-only archive of lispforum.com. The forum was locked to new users and posts and is preserved here as static HTML from a database snapshot taken on 2019-09-07.

Macros: double backquote & unquote

6 posts · 1977 views

Hi!
I am fairly new to CL and have problems with nested backquotes and unquotes.

I am trying something like currying or "partial" (in Clojure) does for functions but here with macros - I want to partially bind macros with parameters in a MACROLET-environment:
(defmacro with-partial-macro (name macro list-of-args &body body)
  `(macrolet ((,name (&rest more-args)
                `(,,macro ,,@list-of-args ,@more-args)))
     ,@body))

(defmacro testmacro (&rest args)
  `(+ ,@args))
Here is the expansion:
TOOLS> (macroexpand-1 '(with-partial-macro partial-plus testmacro (1 2 3)
                         (partial-plus 4 5 6)))
-->
 (MACROLET ((PARTIAL-PLUS (&REST MORE-ARGS)
              `(,TESTMACRO ,1 ,2 ,3 ,@MORE-ARGS)))
   (PARTIAL-PLUS 4 5 6))
The double unquoting with ,, and ,,@ does not work the way I would like:
This
`(,TESTMACRO ,1 ,2 ,3 ,@MORE-ARGS)))
should be
`(TESTMACRO 1 2 3 ,@MORE-ARGS)))
Perhaps someone can help me?

Re: Macros: double backquote & unquote

Well that's certainly a tricky one. My solution looks like that:
(defmacro with-partial-macro (name macro list-of-args &body body)
  `(flet ((,name (&rest more-args)
	    (eval (apply #'list ',macro ,@list-of-args more-args))))
     ,@body))

(defmacro testmacro (&rest args)
  `(+ ,@args))

(with-partial-macro partial-plus testmacro (1 2 (+ 1 2))
   (partial-plus 4 5 (+ 3 3)))

;; => 21
I do not like the EVAL here. The reason I used that is that I didn't find another way to APPLY arguments to a macro. Maybe somebody can post a better version.

Re: Macros: double backquote & unquote

(defmacro with-partial-macro (name macro list-of-args &body body)
  `(macrolet ((,name (&rest more-args)
		(append (list ',macro ,@list-of-args) more-args)))
     ,@body))

(defmacro testmacro (&rest args)
  `(+ ,@args))

(with-partial-macro partial-plus testmacro (1 2 (+ 1 2))
   (partial-plus 4 5 (+ 3 3)))

;; => 21
Couldn't stop playing with it ;) Without nested backquotes (yet).

Re: Macros: double backquote & unquote

(defmacro with-partial-macro (name macro list-of-args &body body)
  `(macrolet ((,name (&rest more-args)
		`(,',macro ,,@list-of-args ,@more-args)))
     ,@body))
Here with nested backquotes; I prefer the former version.

Google for `Quasiquotation in Lisp' by Alan Bawden.

Re: Macros: double backquote & unquote

(defmacro with-partial-macro (name macro list-of-args &body body)
  `(macrolet ((,name (&rest more-args)
		(append '(,macro) ',list-of-args more-args)))
     ,@body))

(defmacro testmacro (&rest args)
  `(+ ,@args))

(defparameter *x* 2)

(defun foo ()
  (let ((n 1))
    (with-partial-macro partial-plus testmacro (n *x* (+ 1 2))
      (partial-plus 4 (* 5 n)))))

(foo) ;; => 15

(setq *x* 3)

(foo) ;; => 16
There was a bug in the former version...

Re: Macros: double backquote & unquote

Hi FAU!

I found an other solution in "On LIsp" in chapter 16 "Macros-Defining Macros" on page 215, where Paul Graham explains the solution step by step.
(defmacro with-partial-macro (name macro list-of-args &body body)
  `(macrolet ((,name (&rest more-args)
                `(,',macro ,@',list-of-args ,@more-args)))
     ,@body))