From: Tamas Papp
Subject: nested backquote question
Date: 
Message-ID: <87hcnamjqp.fsf@pu100877.student.princeton.edu>
I would like to define a macro that defines a macro (via macrolet, to
be used inside a function) which calls a function with the same slot
of two classes.

For a concrete example, I want

(macroexpand-1 '(with-convex-combination (cc rgb1 rgb2 aleph) foo))

to yield

(MACROLET ((CC (ACCESSOR)
             (ONCE-ONLY (ACCESSOR)
                        `(CONVEX-COMBINATION (FUNCALL ,ACCESSOR RGB1)
                                             (FUNCALL ,ACCESSOR RGB2)
                                             ALEPH))))
  FOO)

I tried it like this

(defmacro with-convex-combination ((cc instance1 instance2 alpha)
				&body body)
  "Wrap body in a macrolet so that (cc #'accessor) returns the
convex combination of the slots of instance1 and instance2
accessed by accessor."
  `(macrolet ((,cc (accessor)
	       (once-only (accessor)
		 `(convex-combination (funcall ,accessor ,,instance1)
				      (funcall ,accessor ,,instance2)
				      ,,alpha))))
     ,@body))

which is almost there, except for the three extra commas before rgb1,
rgb2 and aleph:

(MACROLET ((CC (ACCESSOR)
             (ONCE-ONLY (ACCESSOR)
                        `(CONVEX-COMBINATION (FUNCALL ,ACCESSOR ,RGB1)
                                             (FUNCALL ,ACCESSOR ,RGB2)
                                             ,ALEPH))))
  FOO)

Please help me eliminate the commas.  Now I am working on a version
using list, but I would be curious whether it can be done with
backquote.

Thanks,

Tamas

From: Tamas Papp
Subject: Re: nested backquote question
Date: 
Message-ID: <87d4xymi8f.fsf@pu100877.student.princeton.edu>
Tamas Papp <······@gmail.com> writes:

> I would like to define a macro that defines a macro (via macrolet, to
> be used inside a function) which calls a function with the same slot
> of two classes.
>
> For a concrete example, I want
>
> (macroexpand-1 '(with-convex-combination (cc rgb1 rgb2 aleph) foo))
>
> to yield
>
> (MACROLET ((CC (ACCESSOR)
>              (ONCE-ONLY (ACCESSOR)
>                         `(CONVEX-COMBINATION (FUNCALL ,ACCESSOR RGB1)
>                                              (FUNCALL ,ACCESSOR RGB2)
>                                              ALEPH))))
>   FOO)
>
> I tried it like this
>
> (defmacro with-convex-combination ((cc instance1 instance2 alpha)
> 				&body body)
>   "Wrap body in a macrolet so that (cc #'accessor) returns the
> convex combination of the slots of instance1 and instance2
> accessed by accessor."
>   `(macrolet ((,cc (accessor)
> 	       (once-only (accessor)
> 		 `(convex-combination (funcall ,accessor ,,instance1)
> 				      (funcall ,accessor ,,instance2)
> 				      ,,alpha))))
>      ,@body))
>
> which is almost there, except for the three extra commas before rgb1,
> rgb2 and aleph:

I think I figured it out: the answer is ,',:

(defmacro with-convex-combination ((cc instance1 instance2 alpha)
				&body body)
  "Wrap body in a macrolet so that (cc #'accessor) returns the
convex combination of the slots of instance1 and instance2
accessed by accessor."
  `(macrolet ((,cc (accessor)
	       (once-only (accessor)
		 `(convex-combination (funcall ,accessor ,',instance1)
				      (funcall ,accessor ,',instance2)
				      ,',alpha))))
     ,@body))

Is this the standard idiom for doing stuff like this, or is there
something simpler?

Tamas
From: Tobias C. Rittweiler
Subject: Re: nested backquote question
Date: 
Message-ID: <87abt2i9b7.fsf@freebits.de>
Tamas Papp <······@gmail.com> writes:

> (defmacro with-convex-combination ((cc instance1 instance2 alpha)
> 				&body body)
>   "Wrap body in a macrolet so that (cc #'accessor) returns the
> convex combination of the slots of instance1 and instance2
> accessed by accessor."
>   `(macrolet ((,cc (accessor)
> 	       (once-only (accessor)
> 		 `(convex-combination (funcall ,accessor ,',instance1)
> 				      (funcall ,accessor ,',instance2)
> 				      ,',alpha))))
>      ,@body))
>
> Is this the standard idiom for doing stuff like this, or is there
> something simpler?

Don't use MACROLET. 

And if you're just about pruning that one, better prune the whole macro
alltogether:

  (defun make-convex-combinator (alpha instance1 instance2)
    (lambda (accessor)
      (convex-combination (funcall accessor instance1)
                          (funcall accessor instance2)
                          alpha)))

and then use

   (let ((cc (make-convex-combinator alpha instance1 instance2)))
     ...)

instead of

   (with-convex-combination (cc instance1 instance2)
     ...)


  -T.
From: Kent M Pitman
Subject: Re: nested backquote question
Date: 
Message-ID: <u8x8mhzqj.fsf@nhplace.com>
"Tobias C. Rittweiler" <···@freebits.de.invalid> writes:

> Tamas Papp <······@gmail.com> writes:
> 
> > (defmacro with-convex-combination ((cc instance1 instance2 alpha)
> > 				&body body)
> >   "Wrap body in a macrolet so that (cc #'accessor) returns the
> > convex combination of the slots of instance1 and instance2
> > accessed by accessor."
> >   `(macrolet ((,cc (accessor)
> > 	       (once-only (accessor)
> > 		 `(convex-combination (funcall ,accessor ,',instance1)
> > 				      (funcall ,accessor ,',instance2)
> > 				      ,',alpha))))
> >      ,@body))
> >
> > Is this the standard idiom for doing stuff like this, or is there
> > something simpler?
> 
> Don't use MACROLET. 

Well, what Tobias suggests here is one possible answer but, strictly,
his advice here is more prescriptive than theoretically complete.

Using cascaded macros (several macrolet bindings) instead of trying to
do all three levels in one backquote will generally work.  Nested
backquotes are fun but I think never required.  I don't have time to
offer an illustration, but assume someone else can.

So yet another answer is "use MACROLET more". ;)