Quoth the docstring of
special-variable-p is a built-in function in `src/eval.c'.
Probably introduced at or before Emacs version 24.1.
Return non-nil if SYMBOL's global binding has been declared special.
A special variable is one that will be bound dynamically, even in a
context where binding is lexical by default.
Note the subtlety in the last sentence, about how a special variable would be treated in a lexical context (such as your
Quoth the manual entry for
-- Function: special-variable-p symbol
This function returns non-‘nil’ if SYMBOL is a special variable
(i.e., it has a ‘defvar’, ‘defcustom’, or ‘defconst’ variable
definition). Otherwise, the return value is ‘nil’.
Note that since this is a function, it can only return non-‘nil’
for variables which are permanently special, but not for those that
are only special in the current lexical scope.
This tells us that only variables which have been declared as special count as special. So, while
setq will change the global value of
x so long as it is a free variable,
special-variable-p will return non-
nil only after
x is declared special.
Modifying your example a bit may help to highlight why this distinction is important:
;; -*- lexical-binding: t -*-
(defun setq-x ()
(setq x 10))
(defvar y 20)
(let ((x 20))
(message "values x: %s, y: %s\nspecial x: %s, y: %s"
When byte-compiled, this gives:
values x: 20, y: 20
special x: nil, y: t
If the first
x special, then
x would have to be 10 after the second call to
let-bound like a local lexical variable that's in a different scope to that of
The conclusion is that it's fine for users to set undeclared variables (usually user options defined in packages that are yet to be loaded). But Elisp libraries ought to declare their variables or those from other libraries appropriately.
What type of variable binding or variable or symbol is
setq creating, when the variable hasn't been declared prior
setq considers variables without a local lexical value as effectively being dynamic. So in your example,
(setq x 10) is the same as
(set 'x 10) (which wouldn't be the case if
x were a lexical variable). You can see this towards the end of the definition of
DEFUN ("setq", Fsetq, Ssetq, 0, UNEVALLED, 0,
doc: /* Set each SYM to the value of its VAL.
The symbols SYM are variables; they are literal (not evaluated).
The values VAL are expressions; they are evaluated.
Thus, (setq x (1+ y)) sets `x' to the value of `(1+ y)'.
The second VAL is not computed until after the first SYM is set, and so on;
each VAL can use the new value of variables set earlier in the `setq'.
The return value of the `setq' form is the value of the last VAL.
usage: (setq [SYM VAL]...) */)
Lisp_Object val = args, tail = args;
for (EMACS_INT nargs = 0; CONSP (tail); nargs += 2)
Lisp_Object sym = XCAR (tail);
tail = XCDR (tail);
if (!CONSP (tail))
xsignal2 (Qwrong_number_of_arguments, Qsetq, make_fixnum (nargs + 1));
Lisp_Object arg = XCAR (tail);
tail = XCDR (tail);
val = eval_sub (arg);
/* Like for eval_sub, we do not check declared_special here since
it's been done when let-binding. */
= ((!NILP (Vinternal_interpreter_environment) /* Mere optimization! */
&& SYMBOLP (sym))
? Fassq (sym, Vinternal_interpreter_environment)
if (!NILP (lex_binding))
XSETCDR (lex_binding, val); /* SYM is lexically bound. */
Fset (sym, val); /* SYM is dynamically bound. */