The declaration
cl:special
specifies that a variable is special, that is it does not have lexical scope. This covers two cases: if the variable is bound in the dynamic environment (for example by
let
or
let*
), then the value of that binding is used; otherwise the value in the global environment is used, if any. An error is signaled in safe code if there is no value in either environment. When
setq
is used with a variable, the value in the dynamic environment is modified if the variable is bound in the dynamic environment, otherwise the value in the global environment is modified. Dynamic variables can have a different value in each thread because each thread has is own dynamic environment. The global environment is shared between all threads.
In SMP LispWorks access to special variables (excluding constants) is a little slower than in non-SMP LispWorks. It can be speeded up by declarations of the symbol, normally by using by proclaim or declaim.
The speedup will be pretty small overall in most cases, because access to specials is usually a small part of a program. However, if the Profiler identifies some piece of code as a bottleneck, you will want to optimize it, and your optimizations may include proclamation of some variable as global or dynamic.
The three declarations described in this section are extensions to Common Lisp. All declare the symbol to be
cl:special
, along with other information. These three declarations are mutually exclusive between themselves and
cl:special
. That is, declaring a symbol with any of these declarations eliminates the other declaration:
hcl:special-global
declares that the symbol is never bound in the dynamic environment.
In SMP LispWorks the compiler signals error if it detects that a symbol declared as
hcl:special-global
will be bound in the dynamic environment, and at runtime it also signals an error.
In non-SMP LispWorks the compiler gives an error, but there is no runtime check. The runtime behavior is the same as
cl:special
, with all accesses to the symbol in low safety.
hcl:special-global
is very useful, and because of the checks it is reasonably safe. It is useful not only for speed, but also to guard against unintentionally binding variables that should not be bound.
See also defglobal-parameter.
hcl:special-dynamic
declares that the symbol is always bound in the dynamic environment when it is accessed.In high safety code accessing the symbol when it is not bound in the dynamic environment signals an error. In low safety code it may result in unpredictable behavior.
In non-SMP LispWorks the only effect of this declaration is to make all access to the variable low safety.
hcl:special-dynamic
is useful, but because it can lead to unpredictable behavior you need to ensure that you test your program in high safety when you use it.
hcl:special-fast-access
declares that a symbol should be "fast access".
The semantics of the declaration is the same as
cl:special
, except that access to the variable is low safety. In addition, the compiler compiles access to the symbol in a way that speeds up the access, but also introduces a tiny reduction in the speed of the whole system. The balance between these effects is not obvious.
It is not obvious where
hcl:special-fast-access
is useful. If you can ensure that the symbol is always bound or never bound then
hcl:special-dynamic
or
hcl:special-global
are certainly better.
LispWorks User Guide and Reference Manual - 21 Dec 2011