From: Peter Seibel
Subject: Is this legal?
Date: 
Message-ID: <m264t9lvmg.fsf@gigamonkeys.com>
(defun foo ()
  (declare (special bar))
  ;; no reference to BAR in body
  )

If it's legal, what does it mean?

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/

From: Paul F. Dietz
Subject: Re: Is this legal?
Date: 
Message-ID: <vNSdnZ2dnZ1XJyXnnZ2dnUHav96dnZ2dRVn-0J2dnZ0@dls.net>
Peter Seibel wrote:
> (defun foo ()
>   (declare (special bar))
>   ;; no reference to BAR in body
>   )
> 
> If it's legal, what does it mean?
> 
> -Peter
> 

It's legal and it's the same as if the declaration
were omitted.

This is what's known as a 'free' declaration; see
section 3.3.4.

	Paul
From: Kent M Pitman
Subject: Re: Is this legal?
Date: 
Message-ID: <uzmql9kf9.fsf@nhplace.com>
"Paul F. Dietz" <·····@dls.net> writes:

> Peter Seibel wrote:
> > (defun foo ()
> >   (declare (special bar))
> >   ;; no reference to BAR in body
> >   )
> > If it's legal, what does it mean?
> > -Peter
> >
> 
> It's legal and it's the same as if the declaration
> were omitted.

I agree.
 
> This is what's known as a 'free' declaration; see
> section 3.3.4.

Right.

But now, for more fun [and this is beyond the scope of the spec
but is something that most implementations deal with because of
multi-tasking and interrupts], try this one:

Is

 (defun foo ()
   (let ((*foo* 2))
     (declare (special *foo*))))

the same as

 (defun foo () nil)

?

I'd argue that although the former can reasonably be optimized to the
latter, the former has a non-zero probability in some implementations
that an interrupt to the executing process will find *foo* bound to 2,
while the latter doesn't.
From: Nathan Baum
Subject: Re: Is this legal?
Date: 
Message-ID: <dqcfrt$a2s$1@nwrdmz01.dmz.ncs.ea.ibs-infra.bt.com>
Kent M Pitman wrote:
> "Paul F. Dietz" <·····@dls.net> writes:
> 
>> Peter Seibel wrote:
>>> (defun foo ()
>>>   (declare (special bar))
>>>   ;; no reference to BAR in body
>>>   )
>>> If it's legal, what does it mean?
>>> -Peter
>>>
>> It's legal and it's the same as if the declaration
>> were omitted.
> 
> I agree.
>  
>> This is what's known as a 'free' declaration; see
>> section 3.3.4.
> 
> Right.
> 
> But now, for more fun [and this is beyond the scope of the spec
> but is something that most implementations deal with because of
> multi-tasking and interrupts], try this one:
> 
> Is
> 
>  (defun foo ()
>    (let ((*foo* 2))
>      (declare (special *foo*))))
> 
> the same as
> 
>  (defun foo () nil)
> 
> ?
> 
> I'd argue that although the former can reasonably be optimized to the
> latter, the former has a non-zero probability in some implementations
> that an interrupt to the executing process will find *foo* bound to 2,
> while the latter doesn't.

I can't see where in the specification it says that an implementation 
may do whatever it pleases so long as it _appears_ to be obeying the 
specification. Does it say that?

If it doesn't, the answer is clear. The specification says the bindings 
are established, and doesn't make any exceptions in the case that there 
are no forms to be evaluated in the resulting environment. Therefore, 
the bindings _are_ established and the two snippets are _not_ the same.

If it does say implementations only have to _look_ like they're 
conforming, the answer is less clear.

I would say that because you can't tell the difference anyway, and 
because you can't be sure if an implementation would perform the 
optimisation anyway, it would be sensible to trust appearances and act 
as though they weren't the same. That way, in the event you find 
yourself using an implementation which _doesn't_ perform the 
optimisation and your program can tell the difference, you won't be 
surprised. I would also say that if the implementation performs the 
optimisation when your program can tell the difference, it wouldn't be 
conforming.

As an aside, whilst there is a sense in which one might say that two 
functions are the same if they produce the same value, I don't think 
that's entirely correct in this context. For example,

   (defun integer-product (a b)
     (declare (integer a b))
     (* a b))

will always produce the same result as

   (defun integer-product (a b)
     (declare (integer a b))
     (loop for i from 1 to b summing a))

but I wouldn't think of them as 'the same', even if my compiler was 
exceptionally smart and produced the same compiled code for each.