Cleanup Issue SPECIAL-VARIABLE-TEST

Status
For Internal Discussion
Category
ADDITION
References
Declaring Global Variables and Named Constants (pp68-69), Declaration Specifiers (p157)

Problem Description

CLtL does not define a way to test to see if a variable has been proclaimed special (for the purposes of either binding or reference).

Programs such as macros, code-walkers, and program-generating programs may need such information from time to time in order to do certain kinds of reasoning about code-motion, unused variables, etc.

Proposal (SPECIAL-VARIABLE-P)

Add a function SPECIAL-VARIABLE-P by analogy with SPECIAL-FORM-P which is defined as:

SPECIAL-VARIABLE-P symbol &optional environment [Function]

Returns T iff -symbol- names a variable which is SPECIAL in the indicated lexical -environment-. Otherwise, it returns NIL. It is an error if -symbol- is not a symbol. If not supplied, the -environment- defaults to NIL, meaning the null lexical environment.

This function will be useful in determining whether a reference to the variable named by SYMBOL in the indicated ENVIRONMENT will be a special reference.

Note: Since special variable proclamations are pervasive and declarations are not, the technique for determining whether binding the variable named by SYMBOL is not dependent on the surrounding lexical environment. It is instead dependent only on the global environment and on the declarations of the form which would accomplish the binding. Whether the variable has been globally proclaimed special can be determined by doing (SPECIAL-VARIABLE-P 'symbol). Whether the variable is locally declared SPECIAL can be checked only by parsing the declarations looking for (DECLARE ... (SPECIAL ... symbol ...)).

Test Cases

  (PROCLAIM '(SPECIAL SPECIAL-FOO))
  (MACROLET ((TEST (NAME &ENVIRONMENT ENV)
	       `'(,NAME ,(SPECIAL-VARIABLE-P NAME ENV)) ))
    (LIST* (TEST SPECIAL-FOO)				        ;0
	   (TEST FOO)
	   (LET ((SPECIAL-FOO 1) (FOO 1))
	     (LIST* (TEST SPECIAL-FOO)				;1
		    (TEST FOO)
		    (LET ((SPECIAL-FOO 2) (FOO 2))
		      (DECLARE (SPECIAL FOO))
		      (LIST* (TEST SPECIAL-FOO)			;2
			     (TEST FOO)
			     (LET ((SPECIAL-FOO 3) (FOO 3))
			       (LIST (TEST SPECIAL-FOO)		;3
				     (TEST FOO)))))))))
  => ((SPECIAL-FOO T) (FOO NIL)			;0
      (SPECIAL-FOO T) (FOO NIL)			;1
      (SPECIAL-FOO T) (FOO T)			;2
      (SPECIAL-FOO T) (FOO NIL))		;3

Rationale

This would allow programs that reason about other programs to obtain important information about SPECIAL declarations and proclamations.

Current Practice

Interpreters and compilers must, of necessity, have a way to do this internally.

In some implementations, information about special variable proclamations is kept on a symbol's plist, and users eventually "figure out" how to take advantage of that.

In most implementations, getting information about special declarations is neither documented nor easy to "figure out".

Symbolics Genera has undocumented internal function which does this.

Cost to Implementors

By necessity, compilers and interpreters must have a way to get the information returned by this facility. In general, it should just be a matter of providing a program interface to that facility.

Cost to Users

None. This is an upward-compatible extension.

Cost of Non-Adoption

Some code-walkers, macros, etc. would continue be hard to write in a portable way.

Benefits

The cost of non-adoption would be avoided.

Aesthetics

Although SPECIAL variables provide some benefit to Common Lisp, that benefit has not been without price. It's difficult to do proper code analysis if lexical and special variables look the same. The presence of this operator makes it easier to write code which reasons clearly and correctly about other programs, and so will probably tend to improve the aesthetics of such programs.

Discussion

This proposal came to the Cleanup committee from the Japanese community. Pitman wrote it up formally.

Pitman and Moon support SPECIAL-VARIABLE-TEST:SPECIAL-VARIABLE-P.

Edit History