From: Tim Bradshaw
Subject: Declaring variables bound by WITH-x forms SPECIAL
Date: 
Message-ID: <ey3k7hs4s57.fsf@cley.com>
I have a context where I want to have a special variable (but not a
globally special variable) bound to a string stream.  So I wrote this:

    (with-output-to-string (%x%)
      (declare (special %x%))
      ...)

But it immediately occurred to me that this really unlikely to be
correct.  Apart from anything else, it seems to me that a reasonable
implementation of the macro might do:

    (let (%x%)
      ...
      (setf %x% ...)
      ...
      (locally 
        ... user code ...))

I had a brief search, and I couldn't find anywhere where the hyperspec
talked about this, so I'm assuming that by not talking about it it
really is asserting that the binding is lexical, and you can't
reliably declare it special.  So my naive code is really not safe, and
I should actually write:

   (with-output-to-string (x)
     (let ((%x% x))
       (declare (special %x%))
       ...))

Can anyone confirm this?

--tim (note this is not some attempt to critisize the spec for
vagueness, it's an attempt to improve my understanding...)

From: Thomas F. Burdick
Subject: Re: Declaring variables bound by WITH-x forms SPECIAL
Date: 
Message-ID: <xcv8yy88mit.fsf@conquest.OCF.Berkeley.EDU>
Tim Bradshaw <···@cley.com> writes:

> I have a context where I want to have a special variable (but not a
> globally special variable) bound to a string stream.  So I wrote this:
> 
>     (with-output-to-string (%x%)
>       (declare (special %x%))
>       ...)
> 
> But it immediately occurred to me that this really unlikely to be
> correct.

While the section of the spec that guarantees that this works has
already been pointed out, I do agree that it's unlikely to work for
WITH-x macros generally, as in, the ones that other people write.
Since implementations all have to be able to pull out declarations and
docstrings from bodies where they occur, it would have been nice if
there had been standardized tools for doing so, so that they would be
available for user code.  I suspect that a lot of peoples macros don't
behave correctly in some of the edge cases, where their system
analogues do, and a few macro-writing tools would help.  I try to do a
good job of this, but I've caught some obnoxious bugs in my macros
before.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Steven M. Haflich
Subject: Re: Declaring variables bound by WITH-x forms SPECIAL
Date: 
Message-ID: <3E0F5E76.7010504@alum.mit.edu>
Tim Bradshaw wrote:

>     (with-output-to-string (%x%)
>       (declare (special %x%))
>       ...)

> I had a brief search, and I couldn't find anywhere where the hyperspec
> talked about this, so I'm assuming that by not talking about it it
> really is asserting that the binding is lexical, and you can't
> reliably declare it special.  So my naive code is really not safe, and
> I should actually write:
> 
>    (with-output-to-string (x)
>      (let ((%x% x))
>        (declare (special %x%))
>        ...))

There is no question that your second form does what you want,
but there is also no question that your first does so as well.
See the ANS dictionary pages for declare (which mentions
with-output-to-string explicitly) and also the page for special.
From: Frode Vatvedt Fjeld
Subject: Re: Declaring variables bound by WITH-x forms SPECIAL
Date: 
Message-ID: <2hptrksi4a.fsf@vserver.cs.uit.no>
Tim Bradshaw <···@cley.com> writes:

> I have a context where I want to have a special variable (but not a
> globally special variable) bound to a string stream.  So I wrote this:
>
>     (with-output-to-string (%x%)
>       (declare (special %x%))
>       ...)
>
> But it immediately occurred to me that this really unlikely to be
> correct.  Apart from anything else, it seems to me that a reasonable
> implementation of the macro might do:
>
>     (let (%x%)
>       ...
>       (setf %x% ...)
>       ...
>       (locally 
>         ... user code ...))

I'm not quite sure if I undertand your concern correctly, but if it is
the case that you include the special declaration in the "user code"
part of your example expansion, that wouldn't be conforming to CL. The
expansion would have to extract the declaration and insert it at the
correct place, I believe. So in general,

  (with-output-to-string (x)
    (declare <foo>)
    <bar..>)

extracts to

  (let (x)
    (declare <foo>)
    ... (setf x ..) ...
    <bar..>)

That is, any macro, like with-output-to-string, that supports
declarations will have to parse the body into the declaration and code
parts.

-- 
Frode Vatvedt Fjeld
From: Kalle Olavi Niemitalo
Subject: Re: Declaring variables bound by WITH-x forms SPECIAL
Date: 
Message-ID: <873cogeg1r.fsf@Astalo.y2000.kon.iki.fi>
Tim Bradshaw <···@cley.com> writes:

>     (with-output-to-string (%x%)
>       (declare (special %x%))
>       ...)

We discussed this in June, under the subject "macros shuffling
declarations".

(With-output-to-string ...) is a binding form.  If it is told to
bind %X% and (declare (special %x%)) appears at its head, then
CLHS 3.3.4 [1] requires that the declaration affects the binding.

Here is the macroexpansion from Debian CMUCL 3.1.4:

  * (macroexpand-1 '(with-output-to-string (%x%)
                      (declare (special %x% %y%))
                      (foo)
                      (bar)))

  (LET ((%X% (MAKE-STRING-OUTPUT-STREAM)))
    (DECLARE (SPECIAL %X% %Y%))
    (UNWIND-PROTECT (PROGN (FOO) (BAR)) (CLOSE %X%))
    (GET-OUTPUT-STREAM-STRING %X%))
  T

Footnotes: 
[1] I don't write "ANS 3.3.4", because I have only CLHS and not
    the official standard.