Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic Variable Closure in Common Lisp (SBCL)

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?

like image 435
shardulc Avatar asked Jun 05 '26 07:06

shardulc


1 Answers

(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.

like image 185
melpomene Avatar answered Jun 08 '26 00:06

melpomene



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!