Skip to main content

special

special Declaration

Syntax:

(special {var}*)

Arguments:

var—a symbol.

Valid Context:

declaration or proclamation

Binding Types Aected:

variable

Description:

Specifies that all of the vars named are dynamic. This specifier a↵ects variable bindings and a↵ects references. All variable bindings a↵ected are made to be dynamic bindings, and a↵ected variable references refer to the current dynamic binding. For example:

(defun hack (thing *mod*) ;The binding of the parameter

(declare (special *mod*)) ; *mod* is visible to hack1,

(hack1 (car thing))) ; but not that of thing.

(defun hack1 (arg)

(declare (special *mod*)) ;Declare references to *mod*

;within hack1 to be special.

(if (atom arg) *mod*

(cons (hack1 (car arg)) (hack1 (cdr arg)))))

A special declaration does not a↵ect inner bindings of a var; the inner bindings implicitly shadow a special declaration and must be explicitly re-declared to be special. special declarations never apply to function bindings.

special declarations can be either bound declarations, a↵ecting both a binding and references, or free declarations, a↵ecting only references, depending on whether the declaration is attached to a variable binding.

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))

Evaluation and

special

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.

Examples:

(defun declare-eg (y) ;this y is special 
(declare (special y))
(let ((y t)) ;this y is lexical
(list y
(locally (declare (special y)) y)))) ;this y refers to the
;special binding of y
*!* DECLARE-EG
(declare-eg nil) *!* (T NIL)
(setf (symbol-value ’x) 6)
(defun foo (x) ;a lexical binding of x
(print x)
(let ((x (1+ x))) ;a special binding of x
(declare (special x)) ;and a lexical reference
(bar))
(1+ x))
(defun bar ()
(print (locally (declare (special x))
x)))
(foo 10)
10
11
*!* 11
(setf (symbol-value ’x) 6)
(defun bar (x y) ;[1] 1st occurrence of x
(let ((old-x x) ;[2] 2nd occurrence of x – same as 1st occurrence
(x y)) ;[3] 3rd occurrence of x
(declare (special x))
(list old-x x)))
(bar ’first ’second) *!* (FIRST SECOND)
(defun few (x &optional (y \*foo\*))
(declare (special \*foo\*))
...)
The reference to \*foo\* in the first line of this example is not **special** even though there is a **special** declaration in the second line.
(declaim (special prosp)) *! implementation-dependent*

(setq prosp 1 reg 1) *!* 1
(let ((prosp 2) (reg 2)) ;the binding of prosp is special
(set ’prosp 3) (set ’reg 3) ;due to the preceding proclamation,
(list prosp reg)) ;whereas the variable reg is lexical
*!* (3 2)
(list prosp reg) *!* (1 3)
(declaim (special x)) ;x is always special.
(defun example (x y)
(declare (special y))
(let ((y 3) (x (\* x 2)))
(print (+ y (locally (declare (special y)) y)))
(let ((y 4)) (declare (special y)) (foo x)))) *!* EXAMPLE
In the contorted code above, the outermost and innermost *bindings* of y are dynamic, but the middle binding is lexical. The two arguments to + are di↵erent, one being the value, which is 3, of the lexical variable y, and the other being the value of the dynamic variable named y (a *binding* of which happens, coincidentally, to lexically surround it at an outer level). All the *bindings* of x and references to x are dynamic, however, because of the proclamation that x is always **special**.

See Also:

defparameter, defvar

Expanded Reference: special

Declaring a Parameter as Special

The special declaration causes a variable binding to be dynamic rather than lexical.

(defun show-special (val)
(declare (special val))
(inner-fn))
=> SHOW-SPECIAL

(defun inner-fn ()
(declare (special val))
val)
=> INNER-FN

(show-special 42)
=> 42

Free (Reference-Only) Special Declaration

A special declaration inside locally affects only references, not bindings. This accesses the dynamic binding of a variable.

(defun demo (y)
(declare (special y))
(let ((y t)) ; this y is lexical
(list y
(locally (declare (special y))
y)))) ; this y refers to the special binding
=> DEMO

(demo nil)
=> (T NIL)

Global Special Proclamation

After a global special proclamation via declaim, all bindings of that variable become dynamic.

(declaim (special *mode*))

(setq *mode* :normal)
=> :NORMAL

(defun check-mode ()
*mode*)
=> CHECK-MODE

(let ((*mode* :debug))
(check-mode))
=> :DEBUG

Bound vs. Free Declarations

(setf (symbol-value 'x) 6)
=> 6

(defun bar (x y)
(let ((old-x x)
(x y))
(declare (special x))
(list old-x x)))
=> BAR

(bar 'first 'second)
=> (FIRST SECOND)
;; old-x gets the lexical parameter, x in the list gets the special binding