From: Michael Greenberg
Subject: macro writing idiom to ensure proper argment evaluation semantics
Date: 
Message-ID: <gn1M9.1098$io.48325@iad-read.news.verio.net>
I often write macros of the form:

(defmacro my-macro (a b c)
   (let ((aval (gensym))
           (bval (gensym))
           (cval (gensym)))
     `(let ((,aval ,a)
              (,bval ,b)
              (,cval ,c))
        ....  ))

This ensures that arguments are evaluated once (and in the expected order).

Are there other idioms for this?  There are several problems with this
approach:
   - it is verbose
   - it is easy to make a mistake (in the bindings)
   - it is possible to use the wrong variable in the body of the macro

In my lisp machine days I would have used once-only.

(I just starting to use lisp again after more than a decade...no doubt
someone has a 'modern' solution to this problem).

Thanks,

Michael Greenberg

From: Kaz Kylheku
Subject: Re: macro writing idiom to ensure proper argment evaluation semantics
Date: 
Message-ID: <cf333042.0212181506.26abec0a@posting.google.com>
"Michael Greenberg" <··········@scr.siemens.com> wrote in message news:<···················@iad-read.news.verio.net>...
> I often write macros of the form:
> 
> (defmacro my-macro (a b c)
>    (let ((aval (gensym))
>            (bval (gensym))
>            (cval (gensym)))
>      `(let ((,aval ,a)
>               (,bval ,b)
>               (,cval ,c))
>         ....  ))
> 
> This ensures that arguments are evaluated once (and in the expected order).
> 
> Are there other idioms for this? 

Yes, there is this:

  (defun my-function (aval bval cval)
     .... )

  (declaim (inline my-function))

:)
From: Barry Margolin
Subject: Re: macro writing idiom to ensure proper argment evaluation semantics
Date: 
Message-ID: <Fn7M9.65$Qm5.945@paloalto-snr1.gtei.net>
In article <····························@posting.google.com>,
Kaz Kylheku <···@ashi.footprints.net> wrote:
>"Michael Greenberg" <··········@scr.siemens.com> wrote in message
>news:<···················@iad-read.news.verio.net>...
>> I often write macros of the form:
>> 
>> (defmacro my-macro (a b c)
>>    (let ((aval (gensym))
>>            (bval (gensym))
>>            (cval (gensym)))
>>      `(let ((,aval ,a)
>>               (,bval ,b)
>>               (,cval ,c))
>>         ....  ))
>> 
>> This ensures that arguments are evaluated once (and in the expected order).
>> 
>> Are there other idioms for this? 
>
>Yes, there is this:
>
>  (defun my-function (aval bval cval)
>     .... )
>
>  (declaim (inline my-function))

Another is:

(defmacro my-macro (a b c)
  `(funcall #'my-macro-helper-function
            (lambda (...) ....) ,a ,b ,c))

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, 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: Gabe Garza
Subject: Re: macro writing idiom to ensure proper argment evaluation semantics
Date: 
Message-ID: <87smwuwynq.fsf@ix.netcom.com>
Barry Margolin <······@genuity.net> writes:
> Another is:
> 
> (defmacro my-macro (a b c)
>   `(funcall #'my-macro-helper-function
>             (lambda (...) ....) ,a ,b ,c))
> 

Why the explicit use of FUNCALL?

Gabe Garza
From: Barry Margolin
Subject: Re: macro writing idiom to ensure proper argment evaluation semantics
Date: 
Message-ID: <FAlM9.6$iS1.34@paloalto-snr1.gtei.net>
In article <··············@ix.netcom.com>,
Gabe Garza  <·······@ix.netcom.com> wrote:
>Barry Margolin <······@genuity.net> writes:
>> Another is:
>> 
>> (defmacro my-macro (a b c)
>>   `(funcall #'my-macro-helper-function
>>             (lambda (...) ....) ,a ,b ,c))
>> 
>
>Why the explicit use of FUNCALL?

Actually, most of the macros I've seen like this used APPLY, because they
took variable argument lists, e.g.

(defmacro my-macro (&rest args &key ...)
  (apply #'my-macro-helper-function (lambda (...) ....) args))

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, 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: Barry Margolin
Subject: Re: macro writing idiom to ensure proper argment evaluation semantics
Date: 
Message-ID: <Oq1M9.34$Qm5.362@paloalto-snr1.gtei.net>
In article <···················@iad-read.news.verio.net>,
Michael Greenberg <··········@scr.siemens.com> wrote:
>In my lisp machine days I would have used once-only.

So write a ONCE-ONLY macro that expands into code like the example you
gave.  That's typically how the real one worked, although some of them
performed some expansion-time optimizations, like skipping plain variables.

>(I just starting to use lisp again after more than a decade...no doubt
>someone has a 'modern' solution to this problem).

Not AFAIK.  You may be able to find a ONCE-ONLY macro at some FTP archives.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, 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: Joost Kremers
Subject: Re: macro writing idiom to ensure proper argment evaluation semantics
Date: 
Message-ID: <slrnb01965.81.joostkremers@catv0149.extern.kun.nl>
Michael Greenberg wrote:
[macro with multiple gensyms]
> Are there other idioms for this?  There are several problems with this
> approach:
>    - it is verbose
>    - it is easy to make a mistake (in the bindings)
>    - it is possible to use the wrong variable in the body of the macro

paul graham ("ANSI Common Lisp") gives a macro with-gensyms:

(defmacro with-gensyms (syms &body body)
	`(let ,(mapcar #'(lambda (s)
				'(,s (gensym)))
			syms)
		,@body))

so you can write

(with-gensyms (x y z)
	...)

which seems to do what you want.
 
-- 
Joost Kremers		http://baserv.uci.kun.nl/~jkremers
lrwxrwxrwx  1 root  root       11 nov  2 21:37 vi -> emacsclient*
From: Wade Humeniuk
Subject: Re: macro writing idiom to ensure proper argment evaluation semantics
Date: 
Message-ID: <CN1M9.58581$sj3.1706447@news0.telusplanet.net>
"Michael Greenberg" <··········@scr.siemens.com> wrote in message
························@iad-read.news.verio.net...
> I often write macros of the form:
>
> (defmacro my-macro (a b c)
>    (let ((aval (gensym))
>            (bval (gensym))
>            (cval (gensym)))
>      `(let ((,aval ,a)
>               (,bval ,b)
>               (,cval ,c))
>         ....  ))
>
> This ensures that arguments are evaluated once (and in the expected order).
>
> Are there other idioms for this?  There are several problems with this
> approach:
>    - it is verbose
>    - it is easy to make a mistake (in the bindings)
>    - it is possible to use the wrong variable in the body of the macro
>
> In my lisp machine days I would have used once-only.


There is a once-only in

http://www.norvig.com/paip/auxfns.lisp

Wade
From: Frode Vatvedt Fjeld
Subject: Re: macro writing idiom to ensure proper argment evaluation semantics
Date: 
Message-ID: <2h4r9buqza.fsf@vserver.cs.uit.no>
"Wade Humeniuk" <····@nospam.nowhere> writes:

> There is a once-only in
>
> http://www.norvig.com/paip/auxfns.lisp

I happened to read about this in PAIP last night, and I have two
issues with this macro. First, as far as I can tell, it fails to take
symbol-macros into account when trying to determine what is
side-effect free and not. Second, it adresses a problem that is the
responsibility of the compiler. Any reasonable compiler will yield the
same code for something like

  (defun foo (x y)
    (let ((t1 x) (t2 y))
      (bar t1 t2)))

and

  (defun foo (x y)
    (bar x y))

-- 
Frode Vatvedt Fjeld
From: Joe Marshall
Subject: Re: macro writing idiom to ensure proper argment evaluation semantics
Date: 
Message-ID: <of7jlyl6.fsf@ccs.neu.edu>
Frode Vatvedt Fjeld <······@cs.uit.no> writes:

> Second, it adresses a problem that is the
> responsibility of the compiler. Any reasonable compiler will yield the
> same code for something like
> 
>   (defun foo (x y)
>     (let ((t1 x) (t2 y))
>       (bar t1 t2)))
> 
> and
> 
>   (defun foo (x y)
>     (bar x y))

While it should produce virtually identical compiled code, you might
want to avoid creating superfluous bindings in order to make things
easier on the users that want to read the resulting expansion.
From: Barry Margolin
Subject: Re: macro writing idiom to ensure proper argment evaluation semantics
Date: 
Message-ID: <Ek7M9.64$Qm5.907@paloalto-snr1.gtei.net>
In article <············@ccs.neu.edu>, Joe Marshall  <···@ccs.neu.edu> wrote:
>Frode Vatvedt Fjeld <······@cs.uit.no> writes:
>
>> Second, it adresses a problem that is the
>> responsibility of the compiler. Any reasonable compiler will yield the
>> same code for something like
>> 
>>   (defun foo (x y)
>>     (let ((t1 x) (t2 y))
>>       (bar t1 t2)))
>> 
>> and
>> 
>>   (defun foo (x y)
>>     (bar x y))
>
>While it should produce virtually identical compiled code, you might
>want to avoid creating superfluous bindings in order to make things
>easier on the users that want to read the resulting expansion.

If I'm trying to figure out what a macro is doing by looking at the
expansion, I often find it easier if it doesn't do too much of its own
optimization.  The mapping between original and expansion is much easier to
see if all the parameters are inserted the same way.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, 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: Joe Marshall
Subject: Re: macro writing idiom to ensure proper argment evaluation semantics
Date: 
Message-ID: <d6nynbni.fsf@ccs.neu.edu>
Barry Margolin <······@genuity.net> writes:

> >While it should produce virtually identical compiled code, you might
> >want to avoid creating superfluous bindings in order to make things
> >easier on the users that want to read the resulting expansion.
> 
> If I'm trying to figure out what a macro is doing by looking at the
> expansion, I often find it easier if it doesn't do too much of its own
> optimization.  The mapping between original and expansion is much easier to
> see if all the parameters are inserted the same way.

I guess it might depend on how hairy the macro is.  I sometimes have
macros that get nested pretty deep and then looking at code like this:

   (foo x y) 

is *much* preferable to code like this:

(let ((#:G1001 x)
      (#:G1002 y))
  (let ((#:G1003 #:G1001)
        (#:G1004 #:G1002))
    (foo #:G1004 #:G1003)))

But maybe it is just taste.
From: Frode Vatvedt Fjeld
Subject: Re: macro writing idiom to ensure proper argment evaluation semantics
Date: 
Message-ID: <2hr8cetgld.fsf@vserver.cs.uit.no>
Joe Marshall <···@ccs.neu.edu> writes:

> I guess it might depend on how hairy the macro is.  I sometimes have
> macros that get nested pretty deep and then looking at code like
> this:
>
>    (foo x y) 
>
> is *much* preferable to code like this:
>
> (let ((#:G1001 x)
>       (#:G1002 y))
>   (let ((#:G1003 #:G1001)
>         (#:G1004 #:G1002))
>     (foo #:G1004 #:G1003)))
>
> But maybe it is just taste.

I'm a believer in using named temporary variables in macro-expansions,
i.e. by (gensym "foo-"). If you pick these names like you pick normal
variable names, it will be easier to read macro-expansions. Actually,
in many instances it should become _more_ readable this way, because
it's the macro that knows the semantic meaning of the variable, and
hence how to name it properly.

-- 
Frode Vatvedt Fjeld
From: Tim Bradshaw
Subject: Re: macro writing idiom to ensure proper argment evaluation semantics
Date: 
Message-ID: <ey3bs3j3ypl.fsf@cley.com>
* Frode Vatvedt Fjeld wrote:

> Second, it adresses a problem that is the responsibility of the
> compiler. Any reasonable compiler will yield the same code for
> something like

>   (defun foo (x y)
>     (let ((t1 x) (t2 y))
>       (bar t1 t2)))

No, it's not the responsibility of a compiler! One problem is if you
have a macro which expands into something that repeatedly evaluates
one of the arguments to the macro, you typically (but not always) want
to make sure that evaluation happens just once, not lots of times.
(This is as true for a symbol macro as it is for anything else.)
Another problem is that, if the macro's body involves user-written
code, you need to ensure that no spurious name capture happens.


An example of both these issues: I have a macro called SYNCHRONIZED,
calls to which look like this:

(synchronized (form)
  ... code that runs with a lock on FORM ...)

This expands to something that needs to make multiple accesses to the
value of FORM, and to the implementation-dependent lock that it pulls
out from that value.  But a call might be:

(synchronized ((big-enormous-function-that-takes-ages-and-has-side-effects ...))
  ...)

It's essential that this function gets called just exactly once, to
return the lockable object.  So the expansion needs to look like:

(let ((x ,form))
  ... macro-inserted-code ..
  (unwind-protect
    (progn .. user code ...)
    ..more macro-inserted code..))
   
Except this isn't right, because x might be used by the user code, so
it has to gensym a variable name as well:

(defmacro synchronized ((form) &body code)
  (let ((fn (make-symbol "FORM")))
   `(let ((,fn ,form))
      ...)))

The alternative style (which I use increasingly) is this:

(defun call/synchronised (object function)
  ... (funcall fn) ...)

(defmacro synchronized ((form) &body code)
  `(let ((.fn. #'(lambda () ,@code)))
     (declare (dynamic-extent .fn.))
     (call/synchronized ,form .fn.)))

(most of the complexity here is to insert the dynamic-extent
declaration which lets the function be stack consed more easily).

--tim
From: Frode Vatvedt Fjeld
Subject: Re: macro writing idiom to ensure proper argment evaluation semantics
Date: 
Message-ID: <2hznr3szya.fsf@vserver.cs.uit.no>
> * Frode Vatvedt Fjeld wrote:
>
>> Second, it adresses a problem that is the responsibility of the
>> compiler. Any reasonable compiler will yield the same code for
>> something like
>
>>   (defun foo (x y)
>>     (let ((t1 x) (t2 y))
>>       (bar t1 t2)))

Tim Bradshaw <···@cley.com> writes:

> No, it's not the responsibility of a compiler! [...]

I did of course not mean to say it's the compiler's responsibility to
decide which (side-effecting) forms should be evaluated how many
times. The responsibility I was talking of was the discovery and
effective removal of superfluous variable bindings, of which t1 and t2
in the function above were an example.

Your comments and examples were fine, but not relevant to the issue I
was trying to address.

-- 
Frode Vatvedt Fjeld
From: Tim Bradshaw
Subject: Re: macro writing idiom to ensure proper argment evaluation semantics
Date: 
Message-ID: <ey34r9aop0l.fsf@cley.com>
* Frode Vatvedt Fjeld wrote:

> Your comments and examples were fine, but not relevant to the issue I
> was trying to address.

Can you explain what issues these were then?  The original poster was
clearly dealing with exactly the issues that I described, so I'm not
sure what others could possibly be relevant.

--tim
From: Frode Vatvedt Fjeld
Subject: Re: macro writing idiom to ensure proper argment evaluation semantics
Date: 
Message-ID: <2hvg1qth72.fsf@vserver.cs.uit.no>
Tim Bradshaw <···@cley.com> writes:

> Can you explain what issues these were then?

Well, I just did, for the second time, in the paragraph you didn't
quote. I don't think I can do much better.

> The original poster was clearly dealing with exactly the issues that
> I described, so I'm not sure what others could possibly be relevant.

And how long have you been using news? You replied to my posting, and
ostensibly to what I wrote. If you were addressing the original
poster, then you should follow the technical and social conventions
for doing so.

-- 
Frode Vatvedt Fjeld
From: Tim Bradshaw
Subject: Re: macro writing idiom to ensure proper argment evaluation semantics
Date: 
Message-ID: <ey3of7im5a8.fsf@cley.com>
* Frode Vatvedt Fjeld wrote:

> Well, I just did, for the second time, in the paragraph you didn't
> quote. I don't think I can do much better.

Well, you wrote:

 I happened to read about this in PAIP last night, and I have two
 issues with this macro. First, as far as I can tell, it fails to take
 symbol-macros into account when trying to determine what is
 side-effect free and not. Second, it adresses a problem that is the
 responsibility of the compiler. Any reasonable compiler will yield the
 same code for something like

 ...

But the only thing I can understand from this is that you've totally
failed to understand what ONCE-ONLY-type macros are for, which is
solving certain issues in macro writing.  ONCE-ONLY simply doesn't
address a problem that `is the responsibility if the compiler' at all.

> And how long have you been using news? 

Much longer than you, I suspect.

Oh well, i give up.
From: Barry Margolin
Subject: Re: macro writing idiom to ensure proper argment evaluation semantics
Date: 
Message-ID: <fylM9.5$iS1.308@paloalto-snr1.gtei.net>
In article <···············@cley.com>, Tim Bradshaw  <···@cley.com> wrote:
>* Frode Vatvedt Fjeld wrote:
>
>> Well, I just did, for the second time, in the paragraph you didn't
>> quote. I don't think I can do much better.
>
>Well, you wrote:
>
> I happened to read about this in PAIP last night, and I have two
> issues with this macro. First, as far as I can tell, it fails to take
> symbol-macros into account when trying to determine what is
> side-effect free and not. Second, it adresses a problem that is the
> responsibility of the compiler. Any reasonable compiler will yield the
> same code for something like
>
> ...
>
>But the only thing I can understand from this is that you've totally
>failed to understand what ONCE-ONLY-type macros are for, which is
>solving certain issues in macro writing.  ONCE-ONLY simply doesn't
>address a problem that `is the responsibility if the compiler' at all.

Frode wasn't referring to the whole ONCE-ONLY macro, just the specific
optimization that it performs of not creating a rebinding for plain
symbols.  If the symbol is a symbol-macro (which probably didn't exist when
the macro was first written) this will result in an erroneous expansion.
And he felt that it was unnecessary for the macro to perform this
optimization, because any decent compiler should notice that it's a no-op.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, 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: Tim Bradshaw
Subject: Re: macro writing idiom to ensure proper argment evaluation semantics
Date: 
Message-ID: <ey3fzsum3e8.fsf@cley.com>
* Barry Margolin wrote:

> Frode wasn't referring to the whole ONCE-ONLY macro, just the specific
> optimization that it performs of not creating a rebinding for plain
> symbols.  If the symbol is a symbol-macro (which probably didn't exist when
> the macro was first written) this will result in an erroneous expansion.
> And he felt that it was unnecessary for the macro to perform this
> optimization, because any decent compiler should notice that it's a no-op.

Oh, OK, I now see what he's been getting at.  I had completely missed
that, and I think he's obviously right - the compiler should do this
stuff.

Sorry (and sorry to Frode).  I must have been having a bad brain day.

--tim
From: Frode Vatvedt Fjeld
Subject: Re: macro writing idiom to ensure proper argment evaluation semantics
Date: 
Message-ID: <2hisxqt45s.fsf@vserver.cs.uit.no>
Barry Margolin <······@genuity.net> writes:

> If the symbol is a symbol-macro (which probably didn't exist when
> the macro was first written) this will result in an erroneous
> expansion.

Right. I believe this bug could be fixed by using macroexpand, though.
(Just take care to pass it the macro's &env, so that it can discover
symbol-macrolets too.)

-- 
Frode Vatvedt Fjeld
From: Frode Vatvedt Fjeld
Subject: Re: macro writing idiom to ensure proper argment evaluation semantics
Date: 
Message-ID: <2hn0n2t4gk.fsf@vserver.cs.uit.no>
Tim Bradshaw <···@cley.com> writes:

> But the only thing I can understand from this is that you've totally
> failed to understand what ONCE-ONLY-type macros are for, which is
> solving certain issues in macro writing.  ONCE-ONLY simply doesn't
> address a problem that `is the responsibility if the compiler' at
> all.

Well, for the third time, I find that removing superfluous variable
bindings is the responsibility of the compiler. To spell it out:
Control the evaluation of macro arguments by binding them to gensym
variables, without regard to whether this is "really necessary" or
not. All the others who responded seemed to grasp this, although
several held the opinion that removing such bindings helps readability
of macroexpansions, which I find to be a valid counter-argument, even
if I don't share that view.

>> And how long have you been using news? 
>
> Much longer than you, I suspect.

And you still fail to see how anything that the OP didn't ask can
possibly be relevant? Come on!

-- 
Frode Vatvedt Fjeld
From: Pascal Costanza
Subject: Re: macro writing idiom to ensure proper argment evaluation semantics
Date: 
Message-ID: <atr2mb$h2s$1@newsreader2.netcologne.de>
Tim Bradshaw wrote:

> Except this isn't right, because x might be used by the user code, so
> it has to gensym a variable name as well:
> 
> (defmacro synchronized ((form) &body code)
>   (let ((fn (make-symbol "FORM")))
>    `(let ((,fn ,form))
>       ...)))

I still have problems to understand the correct use of functions that 
generate fresh symbols, therefore my question: Why did you use 
make-symbol in this example, but not gensym?

Thanks in advance,
Pascal

-- 
Given any rule, however �fundamental� or �necessary� for science, there 
are always circumstances when it is advisable not only to ignore the 
rule, but to adopt its opposite. - Paul Feyerabend
From: Tim Bradshaw
Subject: Re: macro writing idiom to ensure proper argment evaluation semantics
Date: 
Message-ID: <ey3u1han85y.fsf@cley.com>
* Pascal Costanza wrote:

> I still have problems to understand the correct use of functions that
> generate fresh symbols, therefore my question: Why did you use
> make-symbol in this example, but not gensym?

I don't know - because I do, I guess.  They both create fresh,
uninterned symbols, really the only difference is in the name as far
as I can see.  I guess that's it, actually: I use MAKE-SYMBOL because
it lets me (easily) specify the name, so reading macro expansions is a
bit easier:

(let ((#:out ...)
      (#:normal-completion nil))
  (unwind-protect
    (progn
     (format #:out)
     ...
     (print ... #:out)
     (setf #:normal-completion t))
    (unless #:normal-completion ...)))

is somehow easier for me than:

(let ((#:g13265 ...)
      (#:g13268 ...))
  (unwind-protect
    ...
   (unless #:g13268 ...)))

--tim
From: Duane Rettig
Subject: Re: macro writing idiom to ensure proper argment evaluation semantics
Date: 
Message-ID: <4lm2mssvx.fsf@beta.franz.com>
Tim Bradshaw <···@cley.com> writes:

> * Pascal Costanza wrote:
> 
> > I still have problems to understand the correct use of functions that
> > generate fresh symbols, therefore my question: Why did you use
> > make-symbol in this example, but not gensym?
> 
> I don't know - because I do, I guess.  They both create fresh,
> uninterned symbols, really the only difference is in the name as far
> as I can see.  I guess that's it, actually: I use MAKE-SYMBOL because
> it lets me (easily) specify the name, so reading macro expansions is a
> bit easier:
> 
> (let ((#:out ...)
>       (#:normal-completion nil))
>   (unwind-protect
>     (progn
>      (format #:out)
>      ...
>      (print ... #:out)
>      (setf #:normal-completion t))
>     (unless #:normal-completion ...)))
> 
> is somehow easier for me than:
> 
> (let ((#:g13265 ...)
>       (#:g13268 ...))
>   (unwind-protect
>     ...
>    (unless #:g13268 ...)))

You can get the best of both worlds (mnemonic variable names _and_
identity) by using the optional argument to gensym:

CL-USER(1): (loop for i below 10
                collect (gensym (symbol-name :out))
                collect (gensym (symbol-name :normal-completion)))
(#:OUT26 #:NORMAL-COMPLETION27 #:OUT28 #:NORMAL-COMPLETION29 #:OUT30
 #:NORMAL-COMPLETION31 #:OUT32 #:NORMAL-COMPLETION33 #:OUT34
 #:NORMAL-COMPLETION35 ...)
CL-USER(2): 

This can make debugging much easier when you have multiple
macroexpansions of the same macro within a single function.
Otherwise, you would have too many different variables named #:out ...

-- 
Duane Rettig    ·····@franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182   
From: Jochen Schmidt
Subject: Re: macro writing idiom to ensure proper argment evaluation semantics
Date: 
Message-ID: <atqb61$k78$07$1@news.t-online.com>
Michael Greenberg wrote:

> I often write macros of the form:
> 
> (defmacro my-macro (a b c)
>    (let ((aval (gensym))
>            (bval (gensym))
>            (cval (gensym)))
>      `(let ((,aval ,a)
>               (,bval ,b)
>               (,cval ,c))
>         ....  ))
> 
> This ensures that arguments are evaluated once (and in the expected
> order).
> 
> Are there other idioms for this?  There are several problems with this
> approach:
>    - it is verbose
>    - it is easy to make a mistake (in the bindings)
>    - it is possible to use the wrong variable in the body of the macro
> 
> In my lisp machine days I would have used once-only.
> 
> (I just starting to use lisp again after more than a decade...no doubt
> someone has a 'modern' solution to this problem).

Many implementations provide a macro that makes the rebinding of variables 
easier. In LispWorks this macro is called REBINDING

(defmacro my-macro (a b c)
  (rebinding (a b c)
    ...))

Another issue often seen when writing macros are unintented name collisions 
which can be prevented with GENSYMing the symbols. Again most 
implementations provide a shorthand facility for that:

;(LispWorks)
(defmacro my-macro (a b c)
  (with-unique-names (a b c)
    ...))


ciao,
Jochen

--
http://www.dataheaven.de
From: Frode Vatvedt Fjeld
Subject: Re: macro writing idiom to ensure proper argment evaluation semantics
Date: 
Message-ID: <2h8yynuskn.fsf@vserver.cs.uit.no>
"Michael Greenberg" <··········@scr.siemens.com> writes:

> I often write macros of the form:
>
> (defmacro my-macro (a b c)
>    (let ((aval (gensym))
>            (bval (gensym))
>            (cval (gensym)))
>      `(let ((,aval ,a)
>               (,bval ,b)
>               (,cval ,c))
>         ....  ))

This seems to be a case of manually inlining the "...." code. Are you
sure you can't make it a function and declare it inline?

-- 
Frode Vatvedt Fjeld