common lisp - Why does a lambda return a global variable and not the local variable? -


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.