Special variables in SubL are all (and only) those variables defined globally with DEFVAR or DEFPARAMETER. In addition, the name of each special variable must begin and end with an asterisk character : '*'.
Special variables have indefinite scope and dynamic extent. All other variables have lexical scope and dynamic extent
Variables are introduced via:
- Function call
- A new set of variables for the formal parameters of the function are introduced. The extent of the function arguments is the duration of the function invocation.
- CLET, CMULTIPLE-VALUE-BIND, CDESTRUCTURING-BIND
- These constructs explicitly introduce and initialize new local variables. The extent of these variables is until exit from the constuct.
- CDO, CDOLIST, CSOME, CDOTIMES, CDOHASH
- These iteration constructs explicitly introduce and update local variables which represent the state of the iteration. The extent of these variables is until exit from the iteration construct.
When a local variable is introduced with the same name as a local variable which is already within the current scope and extent, the new variable shadows the outer variable.
The initialization of a local variable is considered to occur within the scope of the new local variable. Consequently, a variable which is shadowing an outer variable cannot be initialized in terms of the outer value. For example, this is not allowed :
(define foo (x) (clet ((x (+ x 1))) (print x)) (ret nil))
However, if the variable is a special variable, the CLET is actually introducing a binding for the special variable, not introducing a new local variable. In this case, the initialization of the binding can be a function of its current value for the variable being bound. For example, this is allowed:
(defvar *some-var* 1) (define foo (x) (clet ((*some-var* (+ *some-var* x))) (print *some-var*)) (ret nil))
The construct RET must be used for a function or macro definition to return its intended result.