From: Iban Hatchond
Subject: apply #'macro stuffs
Date: 
Message-ID: <3A12CF57.DF6C5E24@emi.u-bordeaux.fr>
Hi,
I want to do (apply #'macro list), but we all know that it is
impossible.
But i have a class slot who is a list and i need to give that list to a
macro whose signature is
    (defmacro foo (&reset rest) ...)
and so, I'am stuck.

From: Barry Margolin
Subject: Re: apply #'macro stuffs
Date: 
Message-ID: <yKAQ5.38$725.1065@burlma1-snr2>
In article <·················@emi.u-bordeaux.fr>,
Iban Hatchond  <········@emi.u-bordeaux.fr> wrote:
>Hi,
>I want to do (apply #'macro list), but we all know that it is
>impossible.
>But i have a class slot who is a list and i need to give that list to a
>macro whose signature is
>    (defmacro foo (&reset rest) ...)
>and so, I'am stuck.

The best solution would be to write a function version of the macro, and
redefine the macro so it calls the function:

(defun foo-function (list) ...)
(defmacro foo-macro (&rest rest)
  `(foo-function ',rest))

But if that's not feasible, use EVAL:

(defun foo-function (list)
  (eval `(foo ,@list)))

Then you can (apply #'foo-function list).

-- 
Barry Margolin, ······@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Kent M Pitman
Subject: Re: apply #'macro stuffs
Date: 
Message-ID: <sfwaeaz7uvz.fsf@world.std.com>
Iban Hatchond <········@emi.u-bordeaux.fr> writes:

> Hi,
> I want to do (apply #'macro list), but we all know that it is
> impossible.
> But i have a class slot who is a list and i need to give that list to a
> macro whose signature is
>     (defmacro foo (&reset rest) ...)
> and so, I'am stuck.

Barry Margolin's already extracted the useful parts for you, so if you
want the short answer just read his post here, but for historical
background and analysis on this topic, see my 1980 Lisp Conference paper
"Special Forms in Lisp".  I put it on the web with some markup intended
to make it more readable for a modern audience, since it was written about
an older dialect of Lisp.  

  http://world.std.com/~pitman/Papers/Special-Forms.html

The paper is old but the issues haven't changed much since then.  It's also
probably a fun read for people who are just interseted in Lisp history.
From: Thomas A. Russ
Subject: Re: apply #'macro stuffs
Date: 
Message-ID: <ymisnorzu8q.fsf@sevak.isi.edu>
Iban Hatchond <········@emi.u-bordeaux.fr> writes:

> 
> Hi,
> I want to do (apply #'macro list), but we all know that it is
> impossible.
> But i have a class slot who is a list and i need to give that list to a
> macro whose signature is
>     (defmacro foo (&reset rest) ...)
> and so, I'am stuck.

First off, I will offer a few simple solutions.  If these don't work for
you, then you may need to consider the macroexpand and other solutions
that have been posted.

A) Assuming that you just want to use a particular macro FOO that never
changes:
    (foo (slot instance))

B) For a mapping a particular macro FOO over a list function (instead of
APPLYing it), you may need to introduce a lambda expression:

    (mapcar #'(lambda (x) (foo x))  (slot instance))

C) If the macro used needs to be passed as a parameter at runtime, then
these simple solutions don't really help you, but if you can restructure
your program so that the macro FOO expands into a call to a function
FOO-FUNCTION, you could then apply FOO-FUNCTION instead of the macro
FOO.

====

Why do you want to apply a macro anyway?  Can you give us some more
details on what you are trying to do?



-- 
Thomas A. Russ,  USC/Information Sciences Institute          ···@isi.edu    
From: Xenophon Fenderson the Carbon(d)ated
Subject: Re: apply #'macro stuffs
Date: 
Message-ID: <w4od7fwbfil.fsf@lovecraft.irtnog.org>
>>>>> "Iban" == Iban Hatchond <········@emi.u-bordeaux.fr> writes:

    Iban> Hi, I want to do (apply #'macro list), but we all know that
    Iban> it is impossible. But i have a class slot who is a list and
    Iban> i need to give that list to a macro whose signature is
    Iban> (defmacro foo (&reset rest) ...) and so, I'am stuck.

Obviously, APPLY doesn't work for macro functions.  Wouldn't
MACROEXPAND or MACROEXPAND-1 be more appropriate?

-- 
"Remember - if all you have is an axe, every problem looks like hours of fun."
                                                -- Frossie in the monastery
From: Raymond Wiker
Subject: Re: apply #'macro stuffs
Date: 
Message-ID: <86n1f01i3h.fsf@raw.grenland.fast.no>
········@irtnog.org (Xenophon Fenderson the Carbon(d)ated) writes:

> >>>>> "Iban" == Iban Hatchond <········@emi.u-bordeaux.fr> writes:
> 
>     Iban> Hi, I want to do (apply #'macro list), but we all know that
>     Iban> it is impossible. But i have a class slot who is a list and
>     Iban> i need to give that list to a macro whose signature is
>     Iban> (defmacro foo (&reset rest) ...) and so, I'am stuck.
> 
> Obviously, APPLY doesn't work for macro functions.  Wouldn't
> MACROEXPAND or MACROEXPAND-1 be more appropriate?

        I think this may actually be a case where EVAL is
appropriate... Alternatively, if the macro expands to a single
function call form, it may be possible to use MACROEXPAND first, and
then use APPLY on result - something like

        (let ((form (macroexpand (cons 'macro list))))
                (apply (car form) (cdr form)))

-- 
Raymond Wiker
·············@fast.no
From: Barry Margolin
Subject: Re: apply #'macro stuffs
Date: 
Message-ID: <XaTQ5.7$Pr6.576@burlma1-snr2>
In article <··············@raw.grenland.fast.no>,
Raymond Wiker  <·············@fast.no> wrote:
>        I think this may actually be a case where EVAL is
>appropriate... Alternatively, if the macro expands to a single
>function call form, it may be possible to use MACROEXPAND first, and
>then use APPLY on result - something like
>
>        (let ((form (macroexpand (cons 'macro list))))
>                (apply (car form) (cdr form)))

Shouldn't that be (apply (car form) (mapcar #'eval (cdr form)))?  You still
need to use EVAL to get the arguments to be evaluated.  And since this is
essentially what (eval form) does, what's the point of calling MACROEXPAND
at all?

-- 
Barry Margolin, ······@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: David Bakhash
Subject: Re: apply #'macro stuffs
Date: 
Message-ID: <m21ywa7kxa.fsf@cadet.dsl.speakeasy.net>
Iban Hatchond <········@emi.u-bordeaux.fr> writes:

> I want to do (apply #'macro list), but we all know that it is
> impossible.  But i have a class slot who is a list and i need to
> give that list to a macro whose signature is (defmacro foo (&reset
> rest) ...)  and so, I'am stuck.

One thing that you can do, which hopefully might be useful to you is
to consider extracting the macro's expander function directly.
Namely, you can do:

(eval (funcall (macro-function 'my-macro) list))

This is, in my opinion, the cleanest way to do things.  Clearly, you
need to evaluate something, and that's not an evil thing.  It's just
that macros do substitution, and the evaluation model calls for EVAL
here.  Calling macroexpand is just plain nasty, in my opinion.  I
don't know why people are suggesting it.

The bottom line for macros is that they take a list and transform it.
So you get the list back, and evaluate it.  That's all there is to
it.

dave
From: Barry Margolin
Subject: Re: apply #'macro stuffs
Date: 
Message-ID: <9icR5.59$Pr6.1146@burlma1-snr2>
In article <··············@cadet.dsl.speakeasy.net>,
David Bakhash  <·····@alum.mit.edu> wrote:
>Iban Hatchond <········@emi.u-bordeaux.fr> writes:
>
>> I want to do (apply #'macro list), but we all know that it is
>> impossible.  But i have a class slot who is a list and i need to
>> give that list to a macro whose signature is (defmacro foo (&reset
>> rest) ...)  and so, I'am stuck.
>
>One thing that you can do, which hopefully might be useful to you is
>to consider extracting the macro's expander function directly.
>Namely, you can do:
>
>(eval (funcall (macro-function 'my-macro) list))

This is incorrect.  It should be:

(eval (funcall (macro-function 'my-macro) (cons 'my-macro list)))

Remember, the macro function receives the entire expression as its
argument, not just the argument list -- this is necessary for macros that
use &WHOLE in their lambda-list.

But since this is essentially equivalent to:

(eval (cons 'my-macro list))

I don't see the point of calling MACRO-FUNCTION explicitly.

-- 
Barry Margolin, ······@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: David Bakhash
Subject: Re: apply #'macro stuffs
Date: 
Message-ID: <m3vgtntf1n.fsf@cadet.dsl.speakeasy.net>
Barry Margolin <······@genuity.net> writes:

> >(eval (funcall (macro-function 'my-macro) list))
> 
> This is incorrect.  It should be:
> 
> (eval (funcall (macro-function 'my-macro) (cons 'my-macro list)))

This is the lossage that sometimes happens from having read the spec,
remembering wrong, and never using it. :-)

thanks for the correction.

dave
From: Iban Hatchond
Subject: Re: apply #'macro stuffs
Date: 
Message-ID: <3A154AE5.20ACADB3@emi.u-bordeaux.fr>
As a request here is what i'm trying to do :
    I'm working on Free-CLIM with mike McDonald and Robert Strandh. What I
try to do is some graphical menu (which do not exactly respect the spec).
    So, we have a macro for creating some layout-panes : vertically and
horizontally :

    (defmacro vertically ((&rest options
                                         &key (equalize-width t)
                                         &allow-other-keys) &body
contents)
      (remf options :equalize-width)
      (if equalize-width
           `(make-pane 'vrack-pane ,@options :contents (list ,@contents))
           `(make-pane 'vbox-pane ,@options :contents (list ,@contents))))

what I want is for sub-menu
    (defmethod create-structure ((sub-menu sub-menu))
        (with-slots (items ...) sub-menu
             (apply #'veritically items))) <= I know it doesn't work but
this is exactly what i want to do.

And of course i can't touch or transform the macro (because of the spec).

I will try what you all propose me now and tell you what works or not, but
all ideas are goods.
Thanks.
From: Barry Margolin
Subject: Re: apply #'macro stuffs
Date: 
Message-ID: <DzcR5.60$Pr6.1121@burlma1-snr2>
In article <·················@emi.u-bordeaux.fr>,
Iban Hatchond  <········@emi.u-bordeaux.fr> wrote:
>As a request here is what i'm trying to do :
>    I'm working on Free-CLIM with mike McDonald and Robert Strandh. What I
>try to do is some graphical menu (which do not exactly respect the spec).
>    So, we have a macro for creating some layout-panes : vertically and
>horizontally :
>
>    (defmacro vertically ((&rest options
>                                         &key (equalize-width t)
>                                         &allow-other-keys) &body
>contents)
>      (remf options :equalize-width)
>      (if equalize-width
>           `(make-pane 'vrack-pane ,@options :contents (list ,@contents))
>           `(make-pane 'vbox-pane ,@options :contents (list ,@contents))))
>
>what I want is for sub-menu
>    (defmethod create-structure ((sub-menu sub-menu))
>        (with-slots (items ...) sub-menu
>             (apply #'veritically items))) <= I know it doesn't work but
>this is exactly what i want to do.
>
>And of course i can't touch or transform the macro (because of the spec).

The spec says how the macro should work, but it doesn't say how you
implement it.  You can do:

(defmacro vertically ((&rest options
				     &key (equalize-width t)
				     &allow-other-keys) &body contents)
  `(apply #'vertically-internal ',contents ,@options))

(defun vertically-internal (contents &rest options
                            &key (equalize-internal t) &allow-other-keys)
  (remf options :equalize-width)
  (apply #'make-pane (if equalize-width 'vrack-pane 'vbox-pane)
         :contents contents options))

Now you can do (apply #'vertically-internal ...)

This style of macro writing has another advantage: if you need to make any
changes to how vertically works, you can just redefine vertically-internal.
Normally, if you modify a macro, you have to recompile all the users of the
macro, but since all the real work happens in a function, that's not
necessary.

-- 
Barry Margolin, ······@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Kent M Pitman
Subject: Re: apply #'macro stuffs
Date: 
Message-ID: <sfw7l627fvf.fsf@world.std.com>
Iban Hatchond <········@emi.u-bordeaux.fr> writes:

> As a request here is what i'm trying to do :
>     I'm working on Free-CLIM with mike McDonald and Robert Strandh. What I
> try to do is some graphical menu (which do not exactly respect the spec).
>     So, we have a macro for creating some layout-panes : vertically and
> horizontally :
> 
>     (defmacro vertically ((&rest options
>                            &key (equalize-width t)
>                            &allow-other-keys) &body contents)
>       (remf options :equalize-width)
>       (if equalize-width
>            `(make-pane 'vrack-pane ,@options :contents (list ,@contents))
>            `(make-pane 'vbox-pane ,@options :contents (list ,@contents))))
> 
> what I want is for sub-menu
>     (defmethod create-structure ((sub-menu sub-menu))
>         (with-slots (items ...) sub-menu
>              (apply #'veritically items))) <= I know it doesn't work but
> this is exactly what i want to do.

No, you really can't do this at all.

Your problem extends much more deeply than this.  The problem is that 
create-structure has lost the lexical environment in which the body contents
of vertically would operate, and no amount of apply is going to retrieve it.
At *minimum* you're going to have to have whatever creates the structure for
the submenu capture the "body" that it's working from and turn it into a
lexical closure.
 
In order to untangle this, you need to show how a sub-menu gets constructed
and all dataflow back to whatever provides the equivalent of the CONTENTS
that will go into the VERTICALLY.  

You also need to find and restore the lexical environment for the CONTENTS.

> And of course i can't touch or transform the macro (because of the spec).
> 
> I will try what you all propose me now and tell you what works or not, but
> all ideas are goods.
> Thanks.

I'll walk through a sketch of how to untangle this and show you where I got
bogged:

  (defun arrange-vertically (options contents)
    (destructuring-bind (&rest options 
			 &key (equalize-width t)
			 &allow-other-keys)
	raw-options
      (remf options :equalize-width)
      (apply #'make-pane
             (if equalize-width 'vrack-pane 'vbox-pane)
	     :contents contents
	     options)))

Now this (if you test it, which I didn't) reduces the problem of how to get
OPTIONS and CONTENTS out of the SUB-MENU, but the point is that in this
we're not just putting them back into the path of EVAL (which in the macro
case deals with the lexical environment) but instead we are expecting them 
to be already EVAL'd, which APPLY is not going to do.  So rather than

     (defmethod create-structure ((sub-menu sub-menu)) ;your code, repeated
         (with-slots (items ...) sub-menu
              (apply #'veritically items)))

you're going to do

     (defmethod create-structure ((sub-menu sub-menu))
         (with-slots (items ...) sub-menu
	    (multiple-value-bind (options contents) 
		(EXTRACT-OPTIONS-AND-CONTENTS items)
               (arrange-vertically options contents))))

where it turns out that the items in sub-menu will already have been eval'd
and cached in a proper lexical environment or else EXTRACT-OPTIONS-AND-CONTENTS
is going to need an environment argument somehow passed to it.  Or, of course,
you're going to evaluate all this in the dynamic environment only, but I'm
betting that is going to confuse a lot of callers.

I really strongly recommend that anyone doing a MAKE-INSTANCE of SUB-MENU
not cache code.  If they do, they should cache it as lexical closure objects
to be funcalled (though this makes it hard to pick apart at compile time).

This, at least, is my 10minute analysis.  Maybe wrong, but hopefully a start
for you.  Post more info and maybe I'll look at it more.  Or maybe someone
else will spend 15 minutes and come up with a better answer.