From: rif
Subject: special variables in function declarations
Date: 
Message-ID: <wj03cm18zz3.fsf@five-percent-nation.mit.edu>
In the CL spec, talking about special variables, I find:

-----
When used in a proclamation, a special declaration specifier applies
to all bindings as well as to all references of the mentioned
variables. For example, after

 (declaim (special x))

then in a function definition such as

 (defun example (x) ...)

the parameter x is bound as a dynamic variable rather than as a
lexical variable.
------

I was wondering what the rationale for this was, as I find it quite
counterintuitive.  In particular, it seems to mean that I can't for
declare the types of the parameters to a function (and expect those
type declarations to be used by CMUCL) unless I can somehow also
guarantee that no special variables with the same names as the
parameters will exist at compile time.  

Being more specific, under CMUCL, if I have a file that contains

(declaim (optimize (speed 3) (debug 0) (safety 0)))

(defun df-square (x)
  (declare (type double-float x))
  (* x x))

and compile this file, I get only a single note about coercion of the
result to pointer (and I assume direct double-float arithmetic is
generated).  If, before the function, I add the line

(defparameter x 10)

I get 13 notes about how the type of x is unknown and so generic
arithmetic must be performed.  I understand the explanation at the
level of "Your parameter name was the same as a special variable," but
I don't understand WHY the system works this way.

I also don't see what the advantage is --- how would you make good use
of this feature?

Not complaining, just trying to learn.

Cheers,

rif

From: Kaz Kylheku
Subject: Re: special variables in function declarations
Date: 
Message-ID: <cf333042.0303051546.1fb49adb@posting.google.com>
rif <···@mit.edu> wrote in message news:<···············@five-percent-nation.mit.edu>...
> In the CL spec, talking about special variables, I find:
> 
> -----
> When used in a proclamation, a special declaration specifier applies
> to all bindings as well as to all references of the mentioned
> variables. For example, after
> 
>  (declaim (special x))
> 
> then in a function definition such as
> 
>  (defun example (x) ...)
> 
> the parameter x is bound as a dynamic variable rather than as a
> lexical variable.
> ------
> 
> I was wondering what the rationale for this was, as I find it quite
> counterintuitive. 

I'm not sure whether this is *the* rationale, but consider that it
makes it very easy to use special variables without having to mess
around with declarations. For instance:

  (defparameter *my-custom-context*) ;; implicit (declaim (special
...))

  ;;; ... later ...
 
    (let ((*my-custom-context* (make-context)))
      expr ...)

The binding behavior associated with the symbol itself automatically
gives you the right semantics; without it, *my-custom-context* would
have nothing to do with the dynamic variable. You would have to
remember to add the declarations everywhere you wanted
*my-custom-context* to refer to the dynamic variable rather than the
lexical one!

So the question is, what introduces more programming errors: 1)
mistakenly using a special variable as a lexical variable, or 2)
forgetting to have the special semantics when you want them, and thus
failing to override the dynamic variable?

The first programming problem is solved by always using the universal
naming convention *...* for specials, and never for lexicals.  Another
solution (for name clashes in general, applicable to this case too) is
packages.

The second problem has no neat solution like that which can just be
written in one place; it rears its head wherever you forget to use the
declaration. In the absence of a special symbol attribute, the machine
cannot read your mind and guess that you want that symbol to be
special in a given context.

An intermediate, but clumsy, solution would be to mark the symbol for
dynamic binding semantics, but signal an error whenever an ordinary
binding construct is used for that symbol, e.g.

   (defvar *x* 42)

   (let ((*x* 43))) ;; error, *x* has altered semantics

Then add a special protocol by which the programmer can say ``I know,
allow that anyway''; perhaps extra syntax in the binding constructs or
whatever. That would be IMHO quite a clumsy thing.
 
> I also don't see what the advantage is --- how would you make good use
> of this feature?

For example, try this:

   ;; change print base to hexadecimal, then restore it automagically
   (let ((*print-base* 16))
     (print 255)
     (values))

   (print 255)

Or how about this:

   ;; temporarily redirect output to string

   (defun hello ()
     (format t "Hello~%"))

   (with-output-to-string (*standard-output*)
     (hello))

So you can see how it's advantageous to be able to just use the
ordinary binding constructs to save and restore the bindings of
special variables.
From: Barry Margolin
Subject: Re: special variables in function declarations
Date: 
Message-ID: <ymr9a.11$Nl5.1505@paloalto-snr1.gtei.net>
In article <···············@five-percent-nation.mit.edu>,
rif  <···@mit.edu> wrote:
>
>In the CL spec, talking about special variables, I find:
>
>-----
>When used in a proclamation, a special declaration specifier applies
>to all bindings as well as to all references of the mentioned
>variables. For example, after
>
> (declaim (special x))
>
>then in a function definition such as
>
> (defun example (x) ...)
>
>the parameter x is bound as a dynamic variable rather than as a
>lexical variable.
>------
>
>I was wondering what the rationale for this was, as I find it quite
>counterintuitive.  In particular, it seems to mean that I can't for

This allows you to do thing like:

(let ((*package* ...))
  ...)

in order to change the default package temporarily.  This needs to be a
special binding because *PACKAGE* is used as a default in the functions
that will be called by the body -- it won't generally be referenced
lexically within the body.

>Being more specific, under CMUCL, if I have a file that contains
>
>(declaim (optimize (speed 3) (debug 0) (safety 0)))
>
>(defun df-square (x)
>  (declare (type double-float x))
>  (* x x))
>
>and compile this file, I get only a single note about coercion of the
>result to pointer (and I assume direct double-float arithmetic is
>generated).  If, before the function, I add the line
>
>(defparameter x 10)

Patient: Doctor, it hurts when I do this.
Doctor: Don't do that.

Basically, we assumed that you have enough control over the package that
you're writing your application in that you should be able to prevent name
conflicts within it.  If you don't, you run into the same problem with
function names: you might name your function the same as one that already
exists, which would cause problems.

This is also the reason for the *name* convention for special variables.

-- 
Barry Margolin, ··············@level3.com
Genuity Managed Services, 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: Kent M Pitman
Subject: Re: special variables in function declarations
Date: 
Message-ID: <sfwsmu1cuqr.fsf@shell01.TheWorld.com>
In addition to what Barry said, the fact is that the language used to
have ONLY special variables, long ago, and when we switched to lexical
variables we had to provide the capability to emulate the old behavior
on a per-variable basis.  That's why we don't, as we otherwise might,
require use of *'s around special variables, or do some other even more
radical namespacing trick.

The use of special declarations for anything other than legacy code is 
generally pretty marginal style.  But style is never a hard-and-fast rule,
just a guideline for what to do when you don't have a good reason not to.
From: Pekka P. Pirinen
Subject: Re: special variables in function declarations
Date: 
Message-ID: <uk7f76wcl.fsf@globalgraphics.com>
Other people have provided the rationale for SPECIAL declarations; I
am just curious about the behaviour described here:

rif <···@mit.edu> writes (slightly rearranged):
> (defparameter x 10)
> 
> (defun df-square (x)
>   (declare (type double-float x))
>   (* x x))
> 
> I get 13 notes about how the type of x is unknown and so generic
> arithmetic must be performed.

Why all the notes?  What is going on in the CMUCL compiler here?
Whether or not x is special, the type declaration applies just the
same.  Some exaggerated safety checking?  But this was at SAFETY 0.
-- 
Pekka P. Pirinen
Why did the chicken cross the Moebius strip?