From: rif
Subject: nested macrology question
Date: 
Message-ID: <wj0wtsnjp4d.fsf@five-percent-nation.mit.edu>
Suppose I wanted (note: this is not my real goal, but this is the
simplest distilled example I could come up with that illustrates my
issue) a macro, call it make-applyer, that expands as:

(macroexpand-1 '(make-applyer plus2 + bar baz))

(defmacro plus2 (bar baz)
  `(+ ,bar ,baz))

(macroexpand-1 '(make-applyer prod3 * bar baz quux))

(defmacro prod3 (bar baz quux)
  `(+ ,bar ,baz ,quux))

How could I write such a macro?  The skeleton seems to be

(defmacro make-applyer (name op &rest args)
  `(defmacro ,name ,args
     (,op ,@(mapcar 
             (lambda (a)
               ?????)   
             args))))

but I cannot for the life of me, using my own faculties, what I can
find in google groups, or what I can find in Chapter 16 of On Lisp,
figure out what to put in for ?????.  I need something that takes each
arg (which is available as a symbol at macroexpansion time, IIRC),
and, if the arg is bounds to the symbol foo, puts a ",foo" into the
(nested) macropansion.

Any suggestions?

Cheers,

rif

From: Geoffrey Summerhayes
Subject: Re: nested macrology question
Date: 
Message-ID: <xx1Wd.55037$Vf6.1507881@news20.bellglobal.com>
"rif" <···@mit.edu> wrote in message 
····················@five-percent-nation.mit.edu...
>
> Suppose I wanted (note: this is not my real goal, but this is the
> simplest distilled example I could come up with that illustrates my
> issue) a macro, call it make-applyer, that expands as:
>
> (macroexpand-1 '(make-applyer plus2 + bar baz))
>
> (defmacro plus2 (bar baz)
>  `(+ ,bar ,baz))
>
> (macroexpand-1 '(make-applyer prod3 * bar baz quux))
>
> (defmacro prod3 (bar baz quux)
>  `(+ ,bar ,baz ,quux))
>
> How could I write such a macro?  The skeleton seems to be
>
> (defmacro make-applyer (name op &rest args)
>  `(defmacro ,name ,args
>     (,op ,@(mapcar
>             (lambda (a)
>               ?????)
>             args))))
>
> but I cannot for the life of me, using my own faculties, what I can
> find in google groups, or what I can find in Chapter 16 of On Lisp,
> figure out what to put in for ?????.  I need something that takes each
> arg (which is available as a symbol at macroexpansion time, IIRC),
> and, if the arg is bounds to the symbol foo, puts a ",foo" into the
> (nested) macropansion.
>
> Any suggestions?
>

(defmacro make-applyer (name op &rest args)
  `(defmacro ,name ,args
      (list ',op ,@args)))

--
Geoff 
From: Peter Seibel
Subject: Re: nested macrology question
Date: 
Message-ID: <m31xavl096.fsf@gigamonkeys.com>
"Geoffrey Summerhayes" <·············@hotmail.com> writes:

> "rif" <···@mit.edu> wrote in message 
> ····················@five-percent-nation.mit.edu...
>>
>> Suppose I wanted (note: this is not my real goal, but this is the
>> simplest distilled example I could come up with that illustrates my
>> issue) a macro, call it make-applyer, that expands as:
>>
>> (macroexpand-1 '(make-applyer plus2 + bar baz))
>>
>> (defmacro plus2 (bar baz)
>>  `(+ ,bar ,baz))
>>
>> (macroexpand-1 '(make-applyer prod3 * bar baz quux))
>>
>> (defmacro prod3 (bar baz quux)
>>  `(+ ,bar ,baz ,quux))
>>
>> How could I write such a macro?  The skeleton seems to be
>>
>> (defmacro make-applyer (name op &rest args)
>>  `(defmacro ,name ,args
>>     (,op ,@(mapcar
>>             (lambda (a)
>>               ?????)
>>             args))))
>>
>> but I cannot for the life of me, using my own faculties, what I can
>> find in google groups, or what I can find in Chapter 16 of On Lisp,
>> figure out what to put in for ?????.  I need something that takes each
>> arg (which is available as a symbol at macroexpansion time, IIRC),
>> and, if the arg is bounds to the symbol foo, puts a ",foo" into the
>> (nested) macropansion.
>>
>> Any suggestions?
>>
>
> (defmacro make-applyer (name op &rest args)
>   `(defmacro ,name ,args
>       (list ',op ,@args)))

Or:

  (defmacro make-applyer (name op &rest args)
    `(defmacro ,name ,args
       `(,',op ,,@args)))

if you're into that kind of thing.

-Peter

-- 
Peter Seibel                                     ·····@gigamonkeys.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Geoffrey Summerhayes
Subject: Re: nested macrology question
Date: 
Message-ID: <9x2Wd.55348$Vf6.1519252@news20.bellglobal.com>
"Peter Seibel" <·····@gigamonkeys.com> wrote in message 
···················@gigamonkeys.com...
> "Geoffrey Summerhayes" <·············@hotmail.com> writes:
>
>>
>> (defmacro make-applyer (name op &rest args)
>>   `(defmacro ,name ,args
>>       (list ',op ,@args)))
>
> Or:
>
>  (defmacro make-applyer (name op &rest args)
>    `(defmacro ,name ,args
>       `(,',op ,,@args)))
>
> if you're into that kind of thing.
>

Yeah, but it reminds me of nested ?: operators in C
and looks like someone allergic to punctuation sneezed
on the monitor. :-)

And people complain about the 99-bottles format string...

--
Geoff
From: Barry Margolin
Subject: Re: nested macrology question
Date: 
Message-ID: <barmar-908004.21450304032005@comcast.dca.giganews.com>
In article <·······················@news20.bellglobal.com>,
 "Geoffrey Summerhayes" <·············@hotmail.com> wrote:

> "Peter Seibel" <·····@gigamonkeys.com> wrote in message 
> ···················@gigamonkeys.com...
> > "Geoffrey Summerhayes" <·············@hotmail.com> writes:
> >
> >>
> >> (defmacro make-applyer (name op &rest args)
> >>   `(defmacro ,name ,args
> >>       (list ',op ,@args)))
> >
> > Or:
> >
> >  (defmacro make-applyer (name op &rest args)
> >    `(defmacro ,name ,args
> >       `(,',op ,,@args)))
> >
> > if you're into that kind of thing.
> >
> 
> Yeah, but it reminds me of nested ?: operators in C
> and looks like someone allergic to punctuation sneezed
> on the monitor. :-)
> 
> And people complain about the 99-bottles format string...

Nested backquotes are indeed somewhat ugly, and tricky to learn.  But if 
you start doing lots of macro-defining macros, you'll eventually 
discover that there are just a few patterns that keep reappearing, and 
they'll become idioms to you.

Lisp macros make things that are hard to do in most other languages 
easy, and they make things that are virtually impossible to do in those 
other languages possible, but not necessarily easy or pretty.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: lisplover
Subject: Re: nested macrology question
Date: 
Message-ID: <1110245059.570864.13420@z14g2000cwz.googlegroups.com>
Why not just
(defmacro make-applyer(name op &rest args)
  `(defmacro ,name ,args (,op ,@args)))

I tested in Allegro Trial Version and it worked fine.
(macroexpand-1 '(make-applyer prod3 * bar baz quux))
=> (DEFMACRO PROD3 (BAR BAZ QUUX) (* BAR BAZ QUUX))
From: lisplover
Subject: Re: nested macrology question
Date: 
Message-ID: <1110245433.727256.228310@o13g2000cwo.googlegroups.com>
Sorry I didn't fully understand the original question. You are right.
From: rif
Subject: Re: nested macrology question
Date: 
Message-ID: <wj0oedz84sn.fsf@five-percent-nation.mit.edu>
OK, thanks for all the help so far.  It's really appreicated.  I even
maybe almost understand the answers (OK, I don't really understand
them at a deep level, must continue to ponder).  Unfortunately, I'm
still finding myself stuck.  Let me try a different question.

Suppose I want to generate a macro-defining macro foo that works like this:

(macroexpand-1 '(foo name (blah blah blah (:var v1) (blah (:var v2))))
=>
(defmacro name (v1 v2)
   `(blah blah blah ,v1 (blah ,v2)))

I'm finding that I have this sort of task --- I have to generate
macros by walking a "body" form, and instantiating certain things in
the body as "variables" of the macro.

How would you go about writing something like this?  I've been trying
to do various recursions, and finding that by the time I get down to a
form like (:var v1), it's not clear what to do, since I can't really
return a "naked" ',v1'.

Any help is appreciated.  I'm also interested in general pointers for
material to help me think about this stuff.  This is really
intersting, but definitely one of the trickier parts of CL for me.

Cheers,

rif
From: Pascal Bourguignon
Subject: Re: nested macrology question
Date: 
Message-ID: <874qfrvx5c.fsf@thalassa.informatimago.com>
rif <···@mit.edu> writes:

> OK, thanks for all the help so far.  It's really appreicated.  I even
> maybe almost understand the answers (OK, I don't really understand
> them at a deep level, must continue to ponder).  Unfortunately, I'm
> still finding myself stuck.  Let me try a different question.
> 
> Suppose I want to generate a macro-defining macro foo that works like this:
> 
> (macroexpand-1 '(foo name (blah blah blah (:var v1) (blah (:var v2))))
> =>
> (defmacro name (v1 v2)
>    `(blah blah blah ,v1 (blah ,v2)))
> 
> I'm finding that I have this sort of task --- I have to generate
> macros by walking a "body" form, and instantiating certain things in
> the body as "variables" of the macro.
> 
> How would you go about writing something like this?  I've been trying
> to do various recursions, and finding that by the time I get down to a
> form like (:var v1), it's not clear what to do, since I can't really
> return a "naked" ',v1'.
> 
> Any help is appreciated.  I'm also interested in general pointers for
> material to help me think about this stuff.  This is really
> intersting, but definitely one of the trickier parts of CL for me.


You must dissociate backquote/unquote from the macro.  These features
are totally orthogonal!


Backquote/unquote serves to easily build lists/trees following a
pattern.  Unfortunately, it's harder to use them to build sexps that
produce sexps that produces lists/trees.  But you can use normal
operators to build lists and trees, like CONS, LIST, and LIST*.

Instead of writting/thinking:

    (defmacro name (v1 v2)
        `(blah blah blah ,v1 (blah ,v2)))

write:

    (defmacro name (v1 v2)
        (list 'blah 'blah 'blah v1 (list 'blah v2)))

You can still use backquote/unquote for the toplevel macro if you want.


Now, for your problem, it depends on the complexity of the
modifications you want to implement.  If you only need simple
substitutions in the source tree, you can indeed easily do it walking
and copying the tree while substituting the items.

For more complex (non-isomorphe) modifications, you'd have to
"compile" the source sexp and generate a new sexp from the semantic
data collected in the first phase.  It'd be easier to generate a new
sexp than to try to mutate the original one.


So, assuming the former case:


(defun generate-generator (expression)
    "(blah blah blah (:var v1) (blah (:var v2))))
      --> (list 'blah 'blah 'blah v1 (list 'blah v2))"
  (cond
    ((null expression) nil)
    ((atom expression) `(quote ,expression))
    ((eq :var (first expression)) (second expression))
    (t `(list ,@(mapcar (function generate-generator) expression)))))

[43]> (generate-generator '(blah blah blah (:var v1) (blah (:var v2))))
(LIST 'BLAH 'BLAH 'BLAH V1 (LIST 'BLAH V2))


Then you can use the function in your macro:

> (macroexpand-1 '(foo name (blah blah blah (:var v1) (blah (:var v2))))
> =>
> (defmacro name (v1 v2)
>    `(blah blah blah ,v1 (blah ,v2)))

(defmacro foo (name expression)
    `(defmacro ,name
        ,(collect-variables expression) ;; exercice for the reader
        ,(generate-generator expression)))


-- 
__Pascal_Bourguignon__               _  Software patents are endangering
()  ASCII ribbon against html email (o_ the computer industry all around
/\  1962:DO20I=1.100                //\ the world http://lpf.ai.mit.edu/
    2001:my($f)=`fortune`;          V_/   http://petition.eurolinux.org/
From: rif
Subject: Re: nested macrology question
Date: 
Message-ID: <wj0wtsmc6jg.fsf@five-percent-nation.mit.edu>
> You must dissociate backquote/unquote from the macro.  These features
> are totally orthogonal!

I understood that intellectually, but I hadn't (haven't yet fully)
gotten my head around it.

> Backquote/unquote serves to easily build lists/trees following a
> pattern.  Unfortunately, it's harder to use them to build sexps that
> produce sexps that produces lists/trees.  But you can use normal
> operators to build lists and trees, like CONS, LIST, and LIST*.
> 
> Instead of writting/thinking:
> 
>     (defmacro name (v1 v2)
>         `(blah blah blah ,v1 (blah ,v2)))
> 
> write:
> 
>     (defmacro name (v1 v2)
>         (list 'blah 'blah 'blah v1 (list 'blah v2)))
> 
> You can still use backquote/unquote for the toplevel macro if you want.

Ah, thanks.  This is something I don't really have in my head yet, but
your advice allowed me to make a working version of the macro I
wanted.  I still have to think more about it, but now at least I feel
like my cargo-cult macrology is getting going.

Thank you very much.  I really appreciate your help.

rif
From: Wade Humeniuk
Subject: Re: nested macrology question
Date: 
Message-ID: <XVlWd.3059$ZO2.3003@edtnps84>
rif wrote:
> OK, thanks for all the help so far.  It's really appreicated.  I even
> maybe almost understand the answers (OK, I don't really understand
> them at a deep level, must continue to ponder).  Unfortunately, I'm
> still finding myself stuck.  Let me try a different question.
> 
> Suppose I want to generate a macro-defining macro foo that works like this:
> 
> (macroexpand-1 '(foo name (blah blah blah (:var v1) (blah (:var v2))))
> =>
> (defmacro name (v1 v2)
>    `(blah blah blah ,v1 (blah ,v2)))
> 

I would not do the above like that at all.  I would just write name
as a macro directly.

(defmacro name (v1 v2) `(blah blah blah ,v1 (blah ,v2)))

This is no longer to type than your foo macro.

If you want to create a foo macro because you think it is
more descriptive, then:

(defmacro foo (&body body) `(defmacro ,@body))

Then the above becomes

(foo name (v1 v2) `(blah blah blah ,v1 (blah ,v2)))


You are making your life too difficult.

Wade

	
From: rif
Subject: Re: nested macrology question
Date: 
Message-ID: <wj01xaudl76.fsf@five-percent-nation.mit.edu>
> You are making your life too difficult.
> 
> Wade

The example I gave was a simplification.  I agree that in the context
of that simple example, the solution is too difficult and too
heavyweight --- there is no point in having a macro-defining macro at
all.  However, I used that example just for my understanding, not
because that's what I'm "really trying to do."

rif
From: Wade Humeniuk
Subject: Re: nested macrology question
Date: 
Message-ID: <q32Wd.1708$ZO2.1652@edtnps84>
rif wrote:

> How could I write such a macro?  The skeleton seems to be
> 
> (defmacro make-applyer (name op &rest args)
>   `(defmacro ,name ,args
>      (,op ,@(mapcar 
>              (lambda (a)
>                ?????)   
>              args))))
> 

(defmacro make-applyer (name op &rest args)
   `(defmacro ,name ,args
      `(,',op ,,@args)))

Wade