Page 1 of 1

Macros: double backquote & unquote

Posted: Sat Feb 12, 2011 7:36 am
by churib
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:

Code: Select all

(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:

Code: Select all

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

Code: Select all

`(,TESTMACRO ,1 ,2 ,3 ,@MORE-ARGS)))
should be

Code: Select all

`(TESTMACRO 1 2 3 ,@MORE-ARGS)))
Perhaps someone can help me?

Re: Macros: double backquote & unquote

Posted: Sat Feb 12, 2011 2:42 pm
by FAU
Well that's certainly a tricky one. My solution looks like that:

Code: Select all

(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

Posted: Sat Feb 12, 2011 3:11 pm
by FAU

Code: Select all

(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

Posted: Sat Feb 12, 2011 5:30 pm
by FAU

Code: Select all

(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

Posted: Sun Feb 13, 2011 3:54 am
by FAU

Code: Select all

(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

Posted: Sun Feb 13, 2011 4:25 am
by churib
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.

Code: Select all

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