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
You'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
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:
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: