macro macros 
Author Message
 macro macros

Hi,

The code below shows my attempts at writing a macro that generates
macro code.  I have had to introduce a "let" (in the third example) to
get arguments of the outer macro inserted into the inner macro.

The final attempt does what I want, but is ugly, evaluates "outer-arg"
and (I think) will shadow the variable "inner-copy" (not important in
these stylised examples, but worrying in the code I am writing).  How
should it be done?

Sorry to keep asking questions to this list - if you didn't post such
useful answers I'd go away :-)

Thanks,
Andrew

; single comma at two levels of quotes - would give an error at run-time
(defmacro macro-macro-1 (outer-arg)
  `(defmacro generated (inner-arg)
     `(progn
        (format t "inner-arg" ,inner-arg)
        (format t "outer-arg" ,outer-arg))))
(mac (macro-macro-1 1))

(DEFMACRO GENERATED (INNER-ARG)
  `(PROGN (FORMAT T "inner-arg" ,INNER-ARG) (FORMAT T "outer-arg"
,OUTER-ARG))
)

; two commas in two quotes - leaves an extra comma
(defmacro macro-macro-2 (outer-arg)
  `(defmacro generated (inner-arg)
     `(progn
        (format t "inner-arg" ,inner-arg)
        (format t "outer-arg" ,,outer-arg))))
(mac (macro-macro-2 1))

(DEFMACRO GENERATED (INNER-ARG)
  `(PROGN (FORMAT T "inner-arg" ,INNER-ARG) (FORMAT T "outer-arg" ,1))
)

; an extra "let" - this has the effect i want
(defmacro macro-macro-3 (outer-arg)
  `(defmacro generated (inner-arg)
     (let ((inner-copy ,outer-arg))
       `(progn
          (format t "inner-arg" ,inner-arg)
          (format t "outer-arg" ,inner-copy)))))

(mac (macro-macro-3 1))

(DEFMACRO GENERATED (INNER-ARG)
  (LET ((INNER-COPY 1))
    `(PROGN (FORMAT T "inner-arg" ,INNER-ARG)
       (FORMAT T "outer-arg" ,INNER-COPY)
) )  )

Sent via Deja.com http://www.*-*-*.com/
Before you buy.



Sun, 14 Jul 2002 03:00:00 GMT  
 macro macros

Quote:

> Hi,

> The code below shows my attempts at writing a macro that generates
> macro code.  I have had to introduce a "let" (in the third example) to
> get arguments of the outer macro inserted into the inner macro.

> The final attempt does what I want, but is ugly, evaluates "outer-arg"
> and (I think) will shadow the variable "inner-copy" (not important in
> these stylised examples, but worrying in the code I am writing).  How
> should it be done?

> Sorry to keep asking questions to this list - if you didn't post such
> useful answers I'd go away :-)

> Thanks,
> Andrew

[schnipp]

Quote:
> ; two commas in two quotes - leaves an extra comma
> (defmacro macro-macro-2 (outer-arg)
>   `(defmacro generated (inner-arg)
>      `(progn
>         (format t "inner-arg" ,inner-arg)
>         (format t "outer-arg" ,,outer-arg))))
> (mac (macro-macro-2 1))

> (DEFMACRO GENERATED (INNER-ARG)
>   `(PROGN (FORMAT T "inner-arg" ,INNER-ARG) (FORMAT T "outer-arg" ,1))
> )

Almost.

[20]> (defmacro macro-macro-2 (outer-arg)
  `(defmacro generated (inner-arg)
     `(progn
        (format t "inner-arg" ,inner-arg)
        (format t "outer-arg" ,',outer-arg))))
MACRO-MACRO-2
[21]> (macroexpand-1 '(macro-macro-2 1))
(DEFMACRO GENERATED (INNER-ARG)
  `(PROGN (FORMAT T "inner-arg" ,INNER-ARG) (FORMAT T "outer-arg" 1))
) ;
T

That what you wanted?

Cheers,
Michael



Sun, 14 Jul 2002 03:00:00 GMT  
 macro macros

Quote:

> FYI, very few Lisp programmers are able to write macro-generating macros
> well.  Getting them right is the hallmark of being an accomplished
> macrologist.  And if you can write third-level macros, you're a macro
> wizard.  Good luck in your progress towards that level.

Do you have any examples of the use of third-level macros?

--
Samir Barjoud



Sun, 14 Jul 2002 03:00:00 GMT  
 macro macros


Quote:
>The code below shows my attempts at writing a macro that generates
>macro code.  I have had to introduce a "let" (in the third example) to
>get arguments of the outer macro inserted into the inner macro.

FYI, very few Lisp programmers are able to write macro-generating macros
well.  Getting them right is the hallmark of being an accomplished
macrologist.  And if you can write third-level macros, you're a macro
wizard.  Good luck in your progress towards that level.

--

GTE Internetworking, Powered by BBN, 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.



Mon, 15 Jul 2002 03:00:00 GMT  
 macro macros


Quote:

> > FYI, very few Lisp programmers are able to write macro-generating
macros
> > well.  Getting them right is the hallmark of being an accomplished
> > macrologist.  And if you can write third-level macros, you're a
macro
> > wizard.  Good luck in your progress towards that level.

> Do you have any examples of the use of third-level macros?

I can imagine an example.  I am writing second-level macros because I
have a macro which generates an environment in which variables (not
visible directly to the user) are used to provide some extra
functionality.  This uses macrolet to provide macros within the
environment that can access those variables (as suggested in another
thread here).  So a macro that helps me write such macros could be third
level (I've not written enough to know whether there's anything to
abstract into such a macro, though).

(Thanks for all the replies)

Andrew

Sent via Deja.com http://www.deja.com/
Before you buy.



Mon, 15 Jul 2002 03:00:00 GMT  
 macro macros
The important trick here, as Michael Hudson is obviously aware of, is
that to `pop' two levels in a backquote you use ,',  rather than ,,


Quote:

> > Hi,

> > The code below shows my attempts at writing a macro that generates
> > macro code.  I have had to introduce a "let" (in the third example) to
> > get arguments of the outer macro inserted into the inner macro.

> > The final attempt does what I want, but is ugly, evaluates "outer-arg"
> > and (I think) will shadow the variable "inner-copy" (not important in
> > these stylised examples, but worrying in the code I am writing).  How
> > should it be done?

> > Sorry to keep asking questions to this list - if you didn't post such
> > useful answers I'd go away :-)

> > Thanks,
> > Andrew

> [schnipp]

> > ; two commas in two quotes - leaves an extra comma
> > (defmacro macro-macro-2 (outer-arg)
> >   `(defmacro generated (inner-arg)
> >      `(progn
> >         (format t "inner-arg" ,inner-arg)
> >         (format t "outer-arg" ,,outer-arg))))
> > (mac (macro-macro-2 1))

> > (DEFMACRO GENERATED (INNER-ARG)
> >   `(PROGN (FORMAT T "inner-arg" ,INNER-ARG) (FORMAT T "outer-arg" ,1))
> > )

> Almost.

> [20]> (defmacro macro-macro-2 (outer-arg)
>   `(defmacro generated (inner-arg)
>      `(progn
>         (format t "inner-arg" ,inner-arg)
>         (format t "outer-arg" ,',outer-arg))))
> MACRO-MACRO-2
> [21]> (macroexpand-1 '(macro-macro-2 1))
> (DEFMACRO GENERATED (INNER-ARG)
>   `(PROGN (FORMAT T "inner-arg" ,INNER-ARG) (FORMAT T "outer-arg" 1))
> ) ;
> T

> That what you wanted?

> Cheers,
> Michael



Mon, 15 Jul 2002 03:00:00 GMT  
 macro macros

Quote:

> The important trick here, as Michael Hudson is obviously aware of, is
> that to `pop' two levels in a backquote you use ,',  rather than ,,

Not so much "aware of" as "{*filter*}y minded enough to fiddle until it
works", though I hope I'll be able to remember next time I need to use
it...

Cheers,
M.



Mon, 15 Jul 2002 03:00:00 GMT  
 macro macros

Others have pointed out the ,', trick.  I'll handle another detail that
you (quite wisely) touched upon:

Quote:
>The final attempt does what I want, but is ugly, evaluates "outer-arg"
>and (I think) will shadow the variable "inner-copy" (not important in
>these stylised examples, but worrying in the code I am writing).  How
>should it be done?
> ; an extra "let" - this has the effect i want
> (defmacro macro-macro-3 (outer-arg)
>   `(defmacro generated (inner-arg)
>      (let ((inner-copy ,outer-arg))
>        `(progn
>           (format t "inner-arg" ,inner-arg)
>           (format t "outer-arg" ,inner-copy)))))

The usual solution to this is to use Lisp's GENSYM function to produce a
guaranteed fresh uninterned symbol.  The uninterned part is important,
because it means that the name cannot be used to find the symbol.  The
importance of that is that it means the variable capture problem is
solved, since even if a user typed a symbol with the same name, it
would be DIFFERENT from the GENSYM'd symbol.

(defmacro macro-macro-3 (outer-arg)
  (let ((let-var (gensym "ARG-")))     ;; We need a binding to the
                                      ;;   created variable.
   `(defmacro generated (inner-arg)
      (let ((,let-var ,outer-arg))
        `(progn
           (format t "inner-arg" ,inner-arg)
           (format t "outer-arg" ,,let-var))))))

The technique of using a generated variable is also useful to avoid
evaluating arguments to a macro twice:

(defmacro bad-double (arg)
  `(+ ,arg ,arg))

(defmacro good-double (arg)
  (let ((let-var (gensym "ARG-")))
    `(let ((,let-var ,arg))
       (+ ,let-var ,let-var))))

To see the difference, try the following:

(defvar *foo*)
(setq *foo* 2)
(bad-double (incf *foo*))   => 7    *foo* = 4

(setq *foo* 2)
(good-double (incf *foo*))  => 6    *foo* = 3

That is because bad-double expands into:

  (+ (INCF *FOO*) (INCF *FOO*))

whereas good-double expands into something like:

(LET ((#:ARG-36006 (INCF *FOO*)))
  (+ #:ARG-36006 #:ARG-36006))

-Tom.

--



Mon, 15 Jul 2002 03:00:00 GMT  
 
 [ 8 post ] 

 Relevant Pages 

1. A macro involving two sub-macros - where the 2nd macro needs results from the first

2. macro -vs- macro/codeblock

3. Help with macros writing macros in Bigloo

4. syntax-rules macros with sub-macros

5. Scheme macro source: rewriter-widget, a widely applicable macro interface

6. Macros defining macros with define-syntax

7. symbol-macros and regular macros

8. Question about a macro-defining macro

9. Macro-Defining Macros

10. Local macro within a macro?

11. how much macro is too much macro

12. help sought for macro defining macro

 

 
Powered by phpBB® Forum Software