3 ms·
A closure is a combination of a function and the environment containing the variables it is bound to (closed over) rather than left open (like old LISPs, like e
by barrkel 9y ago
A closure is a combination of a function and the environment containing the variables it is bound to (closed over) rather than left open (like old LISPs, like elisp).
Every function isn't a closure. In particular, elisp lambdas aren't closures because elisp is dynamically bound - the variables are open, they are not closed over. Or with another perspective, the variables are bound in the global context. Either way, elisp closures aren't.
From emacs scratch buffer:
(setq f (let ((x 10))
(lambda ()
(progn
(setq x (+ x 1))
x))))
(funcall f)
11
(funcall f)
12
(setq x 20)
(funcall f)
21
This is because elisp is dynamically bound - it only has one environment (in this example), the global environment (leave aside buffer-local etc. for the moment).
It doesn't matter if you try to create a new environment using a lambda, the same problem still occurs:
(setq g
(lambda (x)
(lambda ()
(progn
(setq x (+ x 1))
x))))
(setq f (funcall g 1))
(funcall f)
22 ;; or whatever you last assigned to x, + 1
- sillysaurus3 9y agoYou're thinking of old elisp. Elisp hasn't been dynamically bound since around 2014. In modern elisp, every function is a closure. If you pass your examples to `(eval ... t)`, you'll see what I mean. Or run `(setq-local lexical-binding t)` before evaluating them in the scratch buffer. > (setq g (lambda (x) (lambda () (progn (setq x (+ x 1)) x)))) (setq f (funcall g 1)) (funcall f) 2 > f (closure ((x . 2) t) nil (progn (setq x (+ x 1)) x)) > (setq x 20) 20 > (funcall f) 3