test #1
i have globally declared variable f
, , function argument named f
:
(defvar f 1) (defun test (f) f)
i call function , returns value of argument:
(test 2) => 2
test #2
i again have globally declared variable f
, , function argument named f
. time, however, function returns lambda
, returns f
:
(defvar f 1) (defun test (f) #'(lambda () f))
i call function , returns lambda
function. call lambda
function , returns value of global f
:
(funcall (test 2)) => 1
i surprised. thought lambda
function closure , return local f
, not global f
. how modify test
function and/or lambda
function lambda
function returns local f
, not global f
?
a pointer online resource discusses particular scoping issue appreciated.
by using defvar
declaring f
special (aka dynamically bound) variable. f
in code there on no longer lexically closed in fact same global variable momentarily changed 2.
because of feature lispers not happy global variables without *earmuffs*
. once have *earmuffs*
it's easier see it:
(defvar *f* 1) ; special variable *f* (defun test (*f*) ; momentarily rebind *f* (format nil "*f* ~a~%" *f*) ; use new value #'(lambda () ; return lambda using *f* *f*)) ; *f* goes being 1 (funcall (test 2)) ; ==> 1 (prints "*f* 2\n")
so lesson is: never make global variables without *earmuffs*
since crazy runtime errors impossible detect. naming convention isn't fashion!
as documentation hyperspec shows how dynamic variables work in examples defparameter
, defvar
. see call (foo) => (p v)
, foo
re-binds *p*
, *v*
during call bar
and, since dynamically bound, bar
uses altered values.