I understand how this code works:
(defvar *nums* '(2 3 5))
(defun print-nums ()
(format t "~a~%" *nums*))
(print-nums)
-> (2 3 5)
-> NIL
I even understand how the new value of the dynamically bound variable *nums* is passed on to print-nums in this code:
(let ((*nums* '(1 2 3)))
(print-nums))
-> (1 2 3)
-> NIL
But why doesn't the code below work the same way?
(defvar *my-nums-f* (let ((*nums* '(1 2 3)))
#'(lambda () (format t "~a~%" *nums*))))
(funcall *my-nums-f*)
-> (2 3 5)
-> NIL
Does the concept of a closure not apply to dynamically bound variables, or am I doing something wrong? If I have wrongly understood the concept of a closure, could someone please explain it to me?
(defvar *my-nums-f* (let ((*nums* '(1 2 3)))
#'(lambda () (format t "~a~%" *nums*))))
Here we set *my-nums-f* to the result of
(let ((*nums* '(1 2 3)))
#'(lambda () (format t "~a~%" *nums*)))
This form starts by dynamically binding *nums* to '(1 2 3), then returning #'(lambda () (format t "~a~%" *nums*)), which is a function. At the end, we reset *nums* back to '(2 3 5).
(funcall *my-nums-f*)
Here we call the function stored in *my-nums-f*, which is (lambda () (format t "~a~%" *nums*)). This function takes the current value of *nums*, which is '(2 3 5).
-> (2 3 5)
-> NIL
You seem to expect that the lambda somehow inlines the current values of all variables used in the function body, which would indeed result in (format t "~a~%" '(1 2 3)) at that point.
But that's not how it works: The function refers to the variable itself, not a shapshot of the variable's value. That's why the function sees whatever the current value of *nums* is at the time it is called.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With