From: Stephan Schweitzer
Subject: Defining macros ?
Date: 
Message-ID: <77od29$jev$1@black.news.nacamar.net>
I have a question about macro definition.

I often see a macro definition like the following :

(defmacro a-macro (value-1 value-2)

   (let ((var-1 (gensym))
           (var-2 (gensym)))

      �(let ((,var-1 ,value-1)
               (,var-2 ,value-2))

           .....)))

I think the second let-form is not necessary and the macro definition
could be written like this :

(defmacro a-macro (value-1 value-2)

   (let ((var-1 (gensym))
           (var-2 (gensym)))

      �(progn

            (setq ,var-1 ,value-1)
            (setq ,var-2 ,value-2)

           .....)))

So my question is :

Is there a difference between the two macro definitions?
And if there is not difference between the to definition which one is better
programming style?

Thanks,

Stephan

From: Barry Margolin
Subject: Re: Defining macros ?
Date: 
Message-ID: <_kPn2.230$oD6.15990@burlma1-snr1.gtei.net>
In article <············@black.news.nacamar.net>,
Stephan Schweitzer <········@global.nacamar.de> wrote:
>I have a question about macro definition.
>
>I often see a macro definition like the following :
>
>(defmacro a-macro (value-1 value-2)
>
>   (let ((var-1 (gensym))
>           (var-2 (gensym)))
>
>      �(let ((,var-1 ,value-1)
>               (,var-2 ,value-2))
>
>           .....)))
>
>I think the second let-form is not necessary and the macro definition
>could be written like this :
>
>(defmacro a-macro (value-1 value-2)
>
>   (let ((var-1 (gensym))
>           (var-2 (gensym)))
>
>      �(progn
>
>            (setq ,var-1 ,value-1)
>            (setq ,var-2 ,value-2)
>
>           .....)))

Your version will work, but it's not the best way to do it.  It will create
lots of global variables, which are unnecessary.  Most compilers will warn
about variables used but not declared; you would have to include DEFVAR
forms to prevent it, e.g.

(let ((var-1 (gensym))
      (var-2 (gensym)))
  `(progn
     (defvar ,var-1 ,value-1)
     (defvar ,var-1 ,value-2)
     ...))

There's also an efficiency aspect: local variables are usually faster to
access than global variables, since you don't have to indirect through a
symbol's value cell, and recent stack pages are likely to be in the
processor's cache.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Don't bother cc'ing followups to me.
From: Lyman S. Taylor
Subject: Re: Defining macros ?
Date: 
Message-ID: <77ohra$f1q@pravda.cc.gatech.edu>
In article <···················@burlma1-snr1.gtei.net>,
Barry Margolin  <······@bbnplanet.com> wrote:
...
>There's also an efficiency aspect: local variables are usually faster to
>access ....

    In space efficiency, they can be a "memory leak".

    The values bound to these hygienic variables will never be garbage 
    collected; they're global.  These new globals will
    always refer to what their value was when the PROGN exited. 
    You could explicitly set them all to NIL at the end of the 
    PROGN. However, that doesn't account for nonlocal exits and 
    seems dubious from a style point of view. 

    Local vars disappear after a short while (at least usually).  :-)
    So they are not a barrier to collection. 

-- 
					
Lyman S. Taylor                "Twinkie Cream; food of the Gods" 
(·····@cc.gatech.edu)                     Jarod, "The Pretender" 
From: Lyman S. Taylor
Subject: Re: Defining macros ?
Date: 
Message-ID: <77ofsl$eqc@pravda.cc.gatech.edu>
In article <············@black.news.nacamar.net>,
Stephan Schweitzer <········@global.nacamar.de> wrote:
>I have a question about macro definition.
...
>      �(progn
>
>            (setq ,var-1 ,value-1)
>            (setq ,var-2 ,value-2)

     In the expanded code. these expressions create two GLOBAL varirables.
     Granted they are unique, so they will not be in "conflict" with
     anything else. 
     [ I think some implementations may automagically turn these into
         global special variables. ] 
     The intent is to create,  in the expanded code,  hygienic, local, 
     nonspecial variables.  That is what LET is for. [ Actually,  the GENSYMs 
     are for the hygiene and are "input" for the LET's construction. ]

     The following is essentially illustrates the above. 

USER(1): (defun foo ( x y )
          (setq new-var1 x )
          (setq new-var2 y )
          (+ new-var1 new-var2 ))
FOO
USER(2): (foo 3 4 )
7
USER(3): new-var1
3
USER(4): new-var2
4

       Whereas

           (defun foo2 ( x y ) 
               (let  ( (new-var21 x )
                       (new-var22 y ) )
                 (+ new-var21 new-var22 )))

       You'll not be able to reference new-var2X after an invocation of
       foo2.


    

-- 
					
Lyman S. Taylor                "Twinkie Cream; food of the Gods" 
(·····@cc.gatech.edu)                     Jarod, "The Pretender" 
From: Kent M Pitman
Subject: Re: Defining macros ?
Date: 
Message-ID: <sfwsodcumkk.fsf@world.std.com>
"Stephan Schweitzer" <········@global.nacamar.de> writes:

> I often see a macro definition like the following :
> 
> (defmacro a-macro (value-1 value-2)
>    (let ((var-1 (gensym))
>          (var-2 (gensym)))
>       `(let ((,var-1 ,value-1)
>              (,var-2 ,value-2)) .....)))
> 
> I think the second let-form is not necessary and the macro definition
> could be written like this :
> 
> (defmacro a-macro (value-1 value-2)
>    (let ((var-1 (gensym))
>          (var-2 (gensym)))
>       `(progn
>             (setq ,var-1 ,value-1)
>             (setq ,var-2 ,value-2) .....)))
> 
> So my question is :
> Is there a difference between the two macro definitions?

In addition to the items cited by Barry to do with globality, the is also
the issue of reentrance.  If you don't bind the var, there's only one
copy and nested calls wil lose.    Remember, the function might be
recursive, so the self-same macro expansion with the same gensyms
might come into play.  It's actually more common to do the following:

 (defmacro a-macro (value-1 value-2)
   `(let ((.var-1. ,value-1)
          (.var-2. ,value-2))
      ...))

This works in the special case that you know the body doesn't have
any client code in it.  If there is client code, you have to worry
they might pick the name .var-1. or .var-2. and you'd collide.
(I usually use dots around the variable name to denote a name of
this kind.)  Another way to handle this problem that sometimes works
is just to do the binding in an ordinary function, as in:

 (defmacro a-macro (value-1 value-2)
   `(a-function ,value-1 ,value-2))
 (defun a-function (value-1 value-2)
   ... regular function definition...)

I prefer this option (in cases where it works and there's a choice
of using it) because if I later change a-function, I don't have to
recompile all the macro callers.

It's an area rich in expressional options in CL, depending on what
your personal style and particular need-of-the-moment is.
From: Kent M Pitman
Subject: Re: Defining macros ?
Date: 
Message-ID: <sfw67a7ztys.fsf@world.std.com>
Incidentally, harlequin uses something called REBINDING which the Lisp
Machine had a similar variation called ONCE-ONLY.  This is a case
where the LispM screwed up, I think, and made its solution overly
complicated (and I have always assumed it was because the Lisp Machine
compiler had a bias toward not liking extra lambda bindings to be
created; the compiler for Harlequin is pretty good about folding out
gratuitous lambda bindings, so it's fine for macros to introduce
them--once again an argument for letting the market sort out tiny details
like this).  Anyway, what is normally written by people as:

  (defmacro foo (var1 var2)
    (let ((v1 (gensym "VAR1"))
          (v2 (gensym "VAR2")))
      `(let ((,v1 ,var1)
             (,v2 ,var2))
         (+ (* ,v1 ,v1)  (* ,v2 ,v2)))))

would be written using REBINDING as follows:

  (defmacro foo (var1 var2 &body forms)
    (rebinding (var1 var2)
      `(+ (* ,var1 ,var1) (* ,var2 ,var2))))

ONCE-ONLY is equivalent, but for some circumstances
involving macros, you have to pass through an environment
argument, as in:

  (defmacro foo (f g &environment env)
    (once-only (f g &environment env)
      ...))

The &ENVIRONMENT was about the fact that ONCE-ONLY doesn't expand
into the LET forms that REBINDING does because it knows the compiler
won't like those bindings, so it tree-walks the body and does the
optimizations associated with finding out if the extra binding
is needed at macro expand time (using techniques already available
in the system and used in the compiler).  But by just using the 
bindings that REBINDING does, it's not necessary to do all that
hair. A portable implementation of REBINDING can be written in a
few lines of code (ok, maybe about 20 lines). 

It's sad that it's not part of CL.  I made a comment about its
absence during the Public Review of the X3J13 draft; this caused
it to come up for a vote of the committee, but it was voted down.

Incidentally, REBINDING has a friend in the gensym arena.  Using it,

 (with-unique-names (a b c) `(let ((,a ...)) ...))

is like

 (let ((a (gensym "A")) (b (gensym "B")) ...) `(let ((,a ...)) ...))

It is also absent and it's a shame.  It's a majorly useful tool
to the macro writer.

(If it helps think about it, there is loose analogy of the form
REBINDING is to LET as WITH-UNIQUE-NAMES is to LAMBDA.  If it doesn't
help you, don't try--some people like this analogy, some hate it.  But
my entire brain is one big analogy engine, and I see analogies where
others often think I'm off the deep end and I do this compulsively.
REBINDING does both the introduction of variables and the setup of
binding; WITH-UNIQUE-NAMES sets up the bindings but doesn't
immediately use them.  Pretty much as do LET and LAMBDA.  Heh.  Well,
it helps to see why there are two of these and both are important.  Or
it helps me anyway.  Unlike LET and LAMBDA, though, I don't recommend
trying to build up one from the other.  It just makes a mess; or, at
least, it has made a mess every time I've tried.  Then again, DO and
DO* also have analogous relationships and yet can't be built from one
another, so it's not fatal to the idea that there's a relationship.
Never mind any of this parenthetical remark if you don't see what I'm
getting at.  It's late and I'm perhaps rambling again.)
From: Christopher R. Barry
Subject: Re: Defining macros ?
Date: 
Message-ID: <87ww2mh9it.fsf@2xtreme.net>
Kent M Pitman <······@world.std.com> writes:


[...]

> But my entire brain is one big analogy engine, and I see analogies
> where others often think I'm off the deep end and I do this
> compulsively.

Hmmmm... I've never done super-well on these

        Dog is to Armageddon
                as
        Basketball is to ???

Christopher
From: Kent M Pitman
Subject: Re: Defining macros ?
Date: 
Message-ID: <sfwhftqtq7b.fsf@world.std.com>
······@2xtreme.net (Christopher R. Barry) writes:

> Kent M Pitman <······@world.std.com> writes:
> 
> > But my entire brain is one big analogy engine, and I see analogies
> > where others often think I'm off the deep end and I do this
> > compulsively.
> 
> Hmmmm... I've never done super-well on these
> 
>         Dog is to Armageddon
>                 as
>         Basketball is to ???

It doesn't quite work that way.  You don't first specify the analogy
and then try to find a commonality to fill it in.  Rather, you notice
a commonality in the matrix
 A is to B
    as
 C is to D
along the A-C and A-B axes, and then that defines the quantity being
measured along each axis.  Then if you know A, B, and C, and the nature
of the shift-on-each-axis, you can construct D.  Or if you know all of
A,B,C,D you can infer properties of D given properties of some of the others.

Since I assume in your example that these terms are chosen randomly, there
really isn't a defining sense of each axis and the answer is tough.

Though if I had to pick a filler for your "???", I'd say "the Heath
Death of the Universe due to gradual Entropy".  (It's the
inanimate/involuntary version of Armageddon, though on the same
physical scope and scale.)  Your mileage may vary.

Not that any of this has to do with Lisp.
From: Howard R. Stearns
Subject: Re: Defining macros ?
Date: 
Message-ID: <36A35A9E.56E5119E@elwood.com>
Here's some code I wrote for WITH-UNIQUE-NAMES and REBINDING.  It would
probably not be right for me to say that this is how these are
implemented in Eclipse, so I won't.  Documentation for the Eclipse
versions are on-line at:

http://www.elwood.com/eclipse/unique.htm
http://www.elwood.com/eclipse/rebinding.htm

(defmacro WITH-UNIQUE-NAMES (vars &body body)
  `(let ,(loop for var in vars
	       collect `(,var (make-symbol ,(symbol-name var))))
     ,@body))

(defmacro REBINDING (vars &body body)	;difficult code here!..
  (loop for var in vars
	for name = (make-symbol (symbol-name var))
	collect `(,name ,var) into renames
	collect ``(,,var ,,name) into temps
	finally (return `(let ,renames
			   (with-unique-names ,vars
			     `(let (,,@temps)
				,,@body))))))

Speaking for Elwood Corporation, we have no problem with Lisp
implementors standardizing on such utilities or their documentation. 
Anyone should feel free to use these defs (supplied by Howard,
individually, not Elwood) or to "quote from" the on-line documentation. 
No warantees on their fitness, etc., etc.... Just program responsibly. 

In return, we welcome any comments, bug reports, etc.  

I'm also curious as to whether people prefer that temps be created with
MAKE-SYMBOL, as above, or GENSYM.  GENSYM obviously helps in nested uses
if you have *PRINT-CIRCLE* turned off, but personally, I'd rather not
have the hairy looking numbers, and I use *print-circle* when I need to.


Kent M Pitman wrote:
> 
> Incidentally, harlequin uses something called REBINDING which the Lisp
> Machine had a similar variation called ONCE-ONLY.  This is a case
> where the LispM screwed up, I think, and made its solution overly
> complicated (and I have always assumed it was because the Lisp Machine
> compiler had a bias toward not liking extra lambda bindings to be
> created; the compiler for Harlequin is pretty good about folding out
> gratuitous lambda bindings, so it's fine for macros to introduce
> them--once again an argument for letting the market sort out tiny details
> like this).  Anyway, what is normally written by people as:
> 
>   (defmacro foo (var1 var2)
>     (let ((v1 (gensym "VAR1"))
>           (v2 (gensym "VAR2")))
>       `(let ((,v1 ,var1)
>              (,v2 ,var2))
>          (+ (* ,v1 ,v1)  (* ,v2 ,v2)))))
> 
> would be written using REBINDING as follows:
> 
>   (defmacro foo (var1 var2 &body forms)
>     (rebinding (var1 var2)
>       `(+ (* ,var1 ,var1) (* ,var2 ,var2))))
> 
> ONCE-ONLY is equivalent, but for some circumstances
> involving macros, you have to pass through an environment
> argument, as in:
> 
>   (defmacro foo (f g &environment env)
>     (once-only (f g &environment env)
>       ...))
> 
> The &ENVIRONMENT was about the fact that ONCE-ONLY doesn't expand
> into the LET forms that REBINDING does because it knows the compiler
> won't like those bindings, so it tree-walks the body and does the
> optimizations associated with finding out if the extra binding
> is needed at macro expand time (using techniques already available
> in the system and used in the compiler).  But by just using the
> bindings that REBINDING does, it's not necessary to do all that
> hair. A portable implementation of REBINDING can be written in a
> few lines of code (ok, maybe about 20 lines).
> 
> It's sad that it's not part of CL.  I made a comment about its
> absence during the Public Review of the X3J13 draft; this caused
> it to come up for a vote of the committee, but it was voted down.
> 
> Incidentally, REBINDING has a friend in the gensym arena.  Using it,
> 
>  (with-unique-names (a b c) `(let ((,a ...)) ...))
> 
> is like
> 
>  (let ((a (gensym "A")) (b (gensym "B")) ...) `(let ((,a ...)) ...))
> 
> It is also absent and it's a shame.  It's a majorly useful tool
> to the macro writer.
> 
> (If it helps think about it, there is loose analogy of the form
> REBINDING is to LET as WITH-UNIQUE-NAMES is to LAMBDA.  If it doesn't
> help you, don't try--some people like this analogy, some hate it.  But
> my entire brain is one big analogy engine, and I see analogies where
> others often think I'm off the deep end and I do this compulsively.
> REBINDING does both the introduction of variables and the setup of
> binding; WITH-UNIQUE-NAMES sets up the bindings but doesn't
> immediately use them.  Pretty much as do LET and LAMBDA.  Heh.  Well,
> it helps to see why there are two of these and both are important.  Or
> it helps me anyway.  Unlike LET and LAMBDA, though, I don't recommend
> trying to build up one from the other.  It just makes a mess; or, at
> least, it has made a mess every time I've tried.  Then again, DO and
> DO* also have analogous relationships and yet can't be built from one
> another, so it's not fatal to the idea that there's a relationship.
> Never mind any of this parenthetical remark if you don't see what I'm
> getting at.  It's late and I'm perhaps rambling again.)
From: Gareth McCaughan
Subject: Re: Defining macros ?
Date: 
Message-ID: <86iue8jder.fsf@g.pet.cam.ac.uk>
Stephan Schweitzer wrote:

> I have a question about macro definition.
> 
> I often see a macro definition like the following :
> 
> (defmacro a-macro (value-1 value-2)
> 
>    (let ((var-1 (gensym))
>            (var-2 (gensym)))
> 
>       �(let ((,var-1 ,value-1)
>                (,var-2 ,value-2))
> 
>            .....)))

I don't believe you. Specifically, I think you've missed out a
backquote somewhere. Otherwise those commas don't make any sense.

> I think the second let-form is not necessary and the macro definition
> could be written like this :
> 
> (defmacro a-macro (value-1 value-2)
> 
>    (let ((var-1 (gensym))
>            (var-2 (gensym)))
> 
>       �(progn
> 
>             (setq ,var-1 ,value-1)
>             (setq ,var-2 ,value-2)
> 
>            .....)))

Nope. You're confused. :-) I take it your point is: we don't
need the inner LET-form, because VAR-1 and VAR-2 are already
bound by the outer one. Unfortunately, that's not the point
at all, because what's being bound by the inner LET-form *isn't*
VAR-1 and VAR-2. It's the new symbols to which VAR-1 and VAR-2
have been bound by the outer LET-form.

I'd better explain that a little more clearly. First of all,
here's a correct (but silly) macro definition of the kind you're
talking about.

    (defmacro a-macro (count)
      (let ((var (gensym)))
        `(let ((,var ,count))
           (loop while (> ,var 0) doing (some-function ,var))) ))

Now, if you stick (a-macro 10) into your code, what happens?
Answer: when the code is compiled, A-MACRO gets invoked. It
produces something that looks a bit like

    (let ((#:G00012 10))
      (loop while (> #:G00012 0) doing (some-function #:G00012)))

and that gets spliced into your program as if you'd written it
instead of writing (a-macro 10). (#:G00012 is the uninterned
symbol created by the call to GENSYM.)

Notice that this code *doesn't* contain "VAR" anywhere. And notice
that if we'd rewritten the macro in your second form it would have
expanded to

    (progn
      (setq #:G00012 10)
      (loop [etc]))

which wouldn't have worked, because #:G00012 wouldn't have had
any binding at the relevant point in your program.

If you're still confused, maybe you aren't very clear on how
macros work, or on what backquote (`) does, or on what those
GENSYMs are for anyway. All these can be fixed, if you ask...

One other thing: Your question suggests that you think the
second form, if it were possible, is better than the first;
presumably on the grounds that binding "new" variables is
less efficient than assigning existing ones. With a good
compiler, there's no reason why that should be true. And
if your LISP system uses generational garbage collection,
it might even be the other way around.

-- 
Gareth McCaughan       Dept. of Pure Mathematics & Mathematical Statistics,
·····@dpmms.cam.ac.uk  Cambridge University, England.
From: Barry Margolin
Subject: Re: Defining macros ?
Date: 
Message-ID: <RHQn2.242$oD6.15990@burlma1-snr1.gtei.net>
In article <··············@g.pet.cam.ac.uk>,
Gareth McCaughan  <·····@dpmms.cam.ac.uk> wrote:
>Stephan Schweitzer wrote:
>
>> I have a question about macro definition.
>> 
>> I often see a macro definition like the following :
>> 
>> (defmacro a-macro (value-1 value-2)
>> 
>>    (let ((var-1 (gensym))
>>            (var-2 (gensym)))
>> 
>>       �(let ((,var-1 ,value-1)
>>                (,var-2 ,value-2))
>> 
>>            .....)))
>
>I don't believe you. Specifically, I think you've missed out a
>backquote somewhere. Otherwise those commas don't make any sense.

There's an 8-bit character before the second "(let".  Its octal code is
264, and it displays as some kind of variant of a single quote or accent.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Don't bother cc'ing followups to me.
From: Gareth McCaughan
Subject: Re: Defining macros ?
Date: 
Message-ID: <86vhi32mrg.fsf@g.pet.cam.ac.uk>
Barry Margolin wrote:

[I said:]
>> I don't believe you. Specifically, I think you've missed out a
>> backquote somewhere. Otherwise those commas don't make any sense.
> 
> There's an 8-bit character before the second "(let".  Its octal code is
> 264, and it displays as some kind of variant of a single quote or accent.

Ah. All my fault for using a font that's missing a lot of
top-bit-set characters. Mea culpa.

-- 
Gareth McCaughan       Dept. of Pure Mathematics & Mathematical Statistics,
·····@dpmms.cam.ac.uk  Cambridge University, England.
From: Stephan Schweitzer
Subject: Re: Defining macros ?
Date: 
Message-ID: <77ppvd$3lm$1@black.news.nacamar.net>
Thank you for your explaination, Gareth McCaughan!

>Stephan Schweitzer wrote:
>
>> I have a question about macro definition.
>>
>> I often see a macro definition like the following :
>>
>> (defmacro a-macro (value-1 value-2)
>>
>>    (let ((var-1 (gensym))
>>            (var-2 (gensym)))
>>
>>       �(let ((,var-1 ,value-1)
           ^ Here is my backquote.

>>                (,var-2 ,value-2))
>>
>>            .....)))
>
>I don't believe you. Specifically, I think you've missed out a
>backquote somewhere. Otherwise those commas don't make any sense.


Maybe i made a mistake, but the backquote is not missing!

>Notice that this code *doesn't* contain "VAR" anywhere. And notice
>that if we'd rewritten the macro in your second form it would have
>expanded to
>
>    (progn
>      (setq #:G00012 10)
>      (loop [etc]))
>
>which wouldn't have worked, because #:G00012 wouldn't have had
>any binding at the relevant point in your program.


This explaination is clear. But if the symbol #:G00012 is new we know that
it is
not used in any other place of the program and so no conflicts (sideeffects)
with
other locations in the program are possible. Also i thought that the new
symbol is treated as a
special variable and so now bindings were necessary. But i guess it is much
better style
to bind the new symbol, but not necessary for the correctness of the
program!

>If you're still confused, maybe you aren't very clear on how
>macros work, or on what backquote (`) does, or on what those
>GENSYMs are for anyway. All these can be fixed, if you ask...
>
>One other thing: Your question suggests that you think the
>second form, if it were possible, is better than the first;
>presumably on the grounds that binding "new" variables is
>less efficient than assigning existing ones. With a good
>compiler, there's no reason why that should be true. And
>if your LISP system uses generational garbage collection,
>it might even be the other way around.


Correct! This is my whole problem. I think it is more efficient to assign a
value to an existing
variable than to bind a variable and initiliaze this variable. Maybe you can
explain why for a
good compiler this is not true and maybe you can explain how generational
garbage collection
works?

So thanks for the good explaination!!!

Stephan
From: Kent M Pitman
Subject: Re: Defining macros ?
Date: 
Message-ID: <sfw3e5bw5gy.fsf@world.std.com>
"Stephan Schweitzer" <········@global.nacamar.de> writes:

> >I don't believe you. Specifically, I think you've missed out a
> >backquote somewhere. Otherwise those commas don't make any sense.
> 
> Maybe i made a mistake, but the backquote is not missing!

In my Emacs-based news reader, the character showed up as \264,
which is presumably some special alphabet that didn't make it through
clearly on everyone's display.  When I quoted back my reply, I
changed it to a real backquote in case people had this confusion
so that I didn't propagate it.

> >Notice that this code *doesn't* contain "VAR" anywhere. And notice
> >that if we'd rewritten the macro in your second form it would have
> >expanded to
> >
> >    (progn
> >      (setq #:G00012 10)
> >      (loop [etc]))
> >
> >which wouldn't have worked, because #:G00012 wouldn't have had
> >any binding at the relevant point in your program.
> 
> This explaination is clear. But if the symbol #:G00012 is new we
> know that it is not used in any other place of the program and so no
> conflicts (sideeffects) with other locations in the program are
> possible. Also i thought that the new symbol is treated as a special
> variable and so now bindings were necessary. But i guess it is much
> better style to bind the new symbol, but not necessary for the
> correctness of the program!

(defmacro cl-prog1 (form1 &rest more-forms) ;give prog1 a nicer name
  `(prog1 ,form1 ,@more-forms))

(defmacro my-prog1 (form1 &rest more-forms) ;an allegedly bad implementation
  (let ((result-var (gensym)))
    `(progn (setq ,result-var ,form1)
            ,@more-forms
            ,result-var)))

(defun foo1a ()
  (let ((x 0))  
    (values (cl-prog1 (cl-prog1 (incf x) (incf x) (incf x))
                      (cl-prog1 (incf x) (incf x) (incf x)))
            x)))

(defun foo1b ()
  (let ((x 0))  
    (values (my-prog1 (my-prog1 (incf x) (incf x) (incf x))
                      (my-prog1 (incf x) (incf x) (incf x)))
            x)))

Now compare what happens in (foo1a) to what happens in (foo1b).  Seems
to be the same, right? Well, people have said you're setting yourself
up and you are.  The above contains no case where the same prog1 is
used dynamically within itself.  To see that, we have to write the
same program "slightly" differently.  (Forgive the ugliness of this
program but I'm trying to come up with something that has the
appropriate properties without thinking too hard--if I spent more time
on it, I might come up with a better example...)

(defun foo2a ()
  (let ((x 0))
    (labels ((do-it (pattern)
               (if (listp pattern)
                   (cl-prog1 (do-it (first pattern))
                                 (dolist (elem (rest pattern))
                                   (do-it elem)))
		   (incf x pattern))))
      (values (do-it '((1 1 1) (1 1 1))) x))))

(defun foo2b ()
  (let ((x 0))
    (labels ((do-it (pattern)
               (if (listp pattern)
                   (my-prog1 (do-it (first pattern))
                                 (dolist (elem (rest pattern))
                                   (do-it elem)))
		   (incf x pattern))))
      (values (do-it '((1 1 1) (1 1 1))) x))))

Now try comparing (foo2a) to (foo2b).

In some interpreters (MCL, I suspect, though I didn't try it) and Harlequin,
you should see "your" bug in the interpreter.  In some, like Allegro, you won't
see your bug until you are compiled.  Both behaviors are conforming--in the
interpreter, macro expansion might be done each time the macro is encountered,
in which case you'll get new gensyms each time.  MCL compiles code always.
My guess, based on observed behavior, is that Allegro expands macros in
evaluated code each time it sees them rather than in one pre-pass.

BUT macro expansion is required in all implementations
when you compile your code, and I bet all implementations--all
conforming implementations--will yield a different result for foo2b
than for the other three if you have done 
  (mapcar 'compile '(foo1a foo1b foo2a foo2b))
At that point, I think foo1a, foo1b, foo2a will return 1 and 6,
while foo2b will return 4 and 6.

When you have looked at these examples long enough to know why foo2b is buggy,
you will know why using free gensyms, like any other free variables whose
use you don't have an elaborate and well-understood protocol for controlling,
is bad.

I tried the example only in Allegro 5.0 on the PC; if my statements
about other implementations are wrong in some way, it's because
I'm too lazy too check a full suite of implementations.
From: Christopher R. Barry
Subject: Re: Defining macros ?
Date: 
Message-ID: <8790f3hsn2.fsf@2xtreme.net>
"Stephan Schweitzer" <········@global.nacamar.de> writes:

[...]

> Correct! This is my whole problem. I think it is more efficient to
> assign a value to an existing variable than to bind a variable and
> initiliaze this variable. Maybe you can explain why for a good
> compiler this is not true and maybe you can explain how generational
> garbage collection works?

Basically, generational collectors are based on the observation that
most objects have short lifetimes (e.g bindings in a macro), so it is
efficient to restrict garbage collection to only the most recently
allocated objects. Whenever a new object is created, it is placed in
the `youngest generation'. When the youngest generation is full, it is
garbage collected. Any objects that survive this garbage collection
(once or more times, it's implementation defined) are moved up to an
older generation, and won't be collected on future passes until the
older generation is full. Once an older generation fills, it and all
younger generations are collected.

Christopher
From: Gareth McCaughan
Subject: Re: Defining macros ?
Date: 
Message-ID: <86sod72lr9.fsf@g.pet.cam.ac.uk>
Stephan Schweitzer wrote:

> Maybe i made a mistake, but the backquote is not missing!

You're right: it's not. It does, though, appear to be some
rather funny top-bit-set character and not the thing I always
think of as the backquote character. Anyway, it's all my
fault: it didn't show up on my screen and I didn't think to
check for the possibility of top-bit-set characters.

> This explaination is clear. But if the symbol #:G00012 is new we
> know that it is not used in any other place of the program and so no
> conflicts (sideeffects) with other locations in the program are
> possible. Also i thought that the new symbol is treated as a special
> variable and so now bindings were necessary.

Well, OK, but then it gets bound as a special variable, which
probably isn't what you want. (Because (1) it's likely to be
less efficient, and (2) the semantics are a bit different.)

>> One other thing: Your question suggests that you think the
>> second form, if it were possible, is better than the first;
>> presumably on the grounds that binding "new" variables is
>> less efficient than assigning existing ones. With a good
>> compiler, there's no reason why that should be true. And
>> if your LISP system uses generational garbage collection,
>> it might even be the other way around.
> 
> Correct! This is my whole problem. I think it is more efficient to
> assign a value to an existing variable than to bind a variable and
> initiliaze this variable. Maybe you can explain why for a good
> compiler this is not true and maybe you can explain how generational
> garbage collection works?

I can try, anyway.

1. Why binding variables is not bad.

Suppose you have a program in which

    (let ((foo 123))
      <do-something-1>)
    <do-something-2>

and

    (setq foo 123)
    <do-something-1>
    <do-something-2>

are interchangeable. Then it must be the case that in <do-something-2>
it doesn't matter what value FOO has: presumably because its value
is not referred to there (unless it gets set again first). A decent
compiler will do variable lifetime analysis, and discover that it
doesn't need to preserve the value of FOO over the first LET form.
It is therefore free to assign the same register to the FOO bound
by that form as is used for FOO just before it. Hence, that LET can
be compiled in exactly the same way as the SETQ.

This is a little overoptimistic: what if the binding of FOO gets
captured by a closure somewhere in <do-something-1>? Well, then
you can't compile the LET in exactly the same way as the SETQ,
but the first form is still probably at least as good as the
second because it saves the outer FOO from needing to be captured.
(And, anyway, most variables don't get captured by closures.)

2. What generational garbage collection is, and why it matters.

It turns out that most garbage becomes garbage rather quickly.
For this reason, the following approach to garbage collection
turns out to be useful.

  - When an object is newly allocated, deem it to be "young".
  - When a garbage collection finds that a young object is
    still in use, deem it to be "old". (More sophisticated
    schemes have more "generations" besides just "young" and
    "old", and/or require more survivals before an object is
    promoted.)
  - On most garbage collections, don't bother looking at the
    "old" objects: just the young ones.

The point of this is that most of your garbage collections can
look only at a fairly small amount of stuff (the "young" objects),
which furthermore contains a lot of garbage. So you gain in
efficiency.

This is only any use if we really can avoid looking at the "old"
objects. For this, we need to be sure of being able to find all
references to the "young" objects without traversing all the "old"
ones. We can do this reasonably efficiently by making use of another
interesting observation: it doesn't often happen that object A
references object B when A is older than B. So, what you can do
is to check every time you do a store operation that might be
putting an object reference into an older object. (This check is
quite expensive, but hopefully you don't have to do it very
often.) When your check indicates that a reference to a "young"
object is being inserted into an "old" object, you note that down
and remember it for future GCs of the "young" objects.

(There are other ways of dealing with the problem, incidentally;
for instance, you can use the virtual memory system to trap all
stores into "old" objects. This, too, makes storing information
in "old" objects expensive.)

OK. What does this have to do with the difference between setting
an existing variable, and binding a new one? Well, suppose that
the existing variable lives in a closure. It might therefore be
stored in a heap object (this is a common way of implementing
closures: a closure is a function plus an environment, and the
environment lives in the heap). If so, it's going to be older
than whatever newly-computed thing you're storing in it; so storing
to it might incur the overhead of the pointer-storing check.
Binding a new variable, on the other hand, can't do that.

-- 
Gareth McCaughan       Dept. of Pure Mathematics & Mathematical Statistics,
·····@dpmms.cam.ac.uk  Cambridge University, England.
From: Erik Naggum
Subject: Re: Defining macros ?
Date: 
Message-ID: <3125445229821476@naggum.no>
* "Stephan Schweitzer" <········@global.nacamar.de>
| I have a question about macro definition.
| 
| I often see a macro definition like the following :
| 
| (defmacro a-macro (value-1 value-2)
|   (let ((var-1 (gensym))
|         (var-2 (gensym)))
|     �(let ((,var-1 ,value-1)
|            (,var-2 ,value-2))
|        .....)))
| 
| I think the second let-form is not necessary and the macro definition
| could be written like this :
| 
| (defmacro a-macro (value-1 value-2)
|   (let ((var-1 (gensym))
|         (var-2 (gensym)))
|     �(progn
|        (setq ,var-1 ,value-1)
|        (setq ,var-2 ,value-2)
|        .....)))
| 
| So my question is :
| 
| Is there a difference between the two macro definitions?

  very much so.  macro functions return a new form that _replaces_ the
  macro call form.  that is, with

(defmacro fast (&body body) `(progn ,@body))

  defined, a call like (fast (setq foo 1) (setq bar 2)) will _expand_ into
  (progn (setq foo 1) (setq bar 2)) and then _that_ form will be analyzed
  (compiled, interpreted, whatever) in place of the original form.  note
  that macros return source code (that is, lists, usually), even though
  they are usually compiled.  macros are functions that transform source
  code, they are not functions that evaluate anything themselves.

  as you can see, the LET binding of the symbols returned by the GENSYMs in
  your example is no longer in scope by the time the returned form is
  analyzed.  the symbols are used in the former version as names of lexical
  variables with names that guarantee no collision with other symbols that
  may be used in both the macro body and the caller's scope.  that is, with

(defmacro repeat (count &body body) `(dotimes (i ,count) ,@body))

  a call to the macro REPEAT like this would be _very_ confusing:

(do ((i 0 (1+ i))
     (length (length string)))
    ((= i length))
  (repeat 4
    (write-char (char string i))))

  and this, incidentally, is why Scheme proponents are opposed to macros in
  Common Lisp.  however, it is sometimes useful to export a binding from
  the macro to the macro body, as in the macro lexically bound by the macro
  expansion form wrapping the body of a DEFMETHOD: CALL-NEXT-METHOD, and in
  the macro available to return from a LOOP: LOOP-FINISH.  (if you didn't
  get this point, keep it for later.)

  use the function MACROEXPAND to see what happens at a macro call point.
  you give it a macro call form, either read from a stream or quoted if a
  literal in the function call.

| And if there is not difference between the to definition which one is
| better programming style?

  the latter definition is not only different, it is in error, for reasons
  I hope I have made clear, so you should never use it.

#:Erik