After reading documentation about the declaration SPECIAL, the special operator LET, the macro DEFVAR, and several questions here at StackOverflow about the dynamic versus lexical scoping in Common Lisp, as, for instance, this, I still can't understand the following behaviour after evaluating these forms in SBCL.
;; x is a free variable
CL-USER> (defun fn ()
(print x))
; in: DEFUN FN
; (PRINT X)
;
; caught WARNING:
; undefined variable: X
;
; compilation unit finished
; Undefined variable:
; X
; caught 1 WARNING condition
FN
CL-USER> (describe 'x)
COMMON-LISP-USER::X
[symbol]
; No value
CL-USER> (let ((x 'dinamic_1st_binding))
(declare (special x))
(print x)
(fn)
(let ((x 'dinamic_2nd_binding))
(declare (special x))
(print x)
(fn))
(let ((x 'lexical_1st_binding))
(print x)
(fn))
(values))
DINAMIC_1ST_BINDING
DINAMIC_1ST_BINDING
DINAMIC_2ND_BINDING
DINAMIC_2ND_BINDING
LEXICAL_1ST_BINDING
DINAMIC_1ST_BINDING
; No value
;; x is defvar'ed as a top level form
CL-USER> (defvar x 'dinamic_global_binding)
X
CL-USER> (describe 'x)
COMMON-LISP-USER::X
[symbol]
X names a special variable:
Value: DINAMIC_GLOBAL_BINDING
; No value
CL-USER> (let ((x 'dinamic_1st_binding))
(declare (special x))
(print x)
(fn)
(let ((x 'dinamic_2nd_binding))
(declare (special x))
(print x)
(fn))
(let ((x 'lexical_1st_binding))
(print x)
(fn))
(values))
DINAMIC_1ST_BINDING
DINAMIC_1ST_BINDING
DINAMIC_2ND_BINDING
DINAMIC_2ND_BINDING
LEXICAL_1ST_BINDING
LEXICAL_1ST_BINDING
; No value
Why does the third call to fn
, before the variable x
is defvar'ed, prints DINAMIC_1ST_BINDING
and after the variable x
is defvar'ed it prints LEXICAL_1ST_BINDING
?