(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/
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
"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.
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.