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.