EDIT: (all the posts in Org format) [https://github.com/tonyaldon/posts](https://github.com/tonyaldon/posts)
Hi Emacsers,
I've spent some time learning Elisp closures and lexical binding.
Although the documentation is clear with simple examples, I needed to to play with other examples to get my bearings.
As you might be interested, I share them with you :)
The first section contains the info nodes and help corresponding to the examples.
The second section shows 10 "basic" examples using `lexical-binding`, `lambda`, `defun`, `let`, `lexical-let`, `setq` and `defvar`.
And the third section shows a more advanced example using `lambda`, `let`, `dolist` and `defun`.
Have a nice day,
ps: In the documentation, we can read "Lexical binding is also more compatible with concurrency, which was added to Emacs in version 26.1.".
Is someone know why is this? And can you indicate me the files in the emacs source code where I can see this benefits? I'm really curious... thank you.
# info and help
Info nodes:
* M-x eval-expression RET (info "(elisp)Variable Scoping")
* M-x eval-expression RET (info "(elisp)Closures")
help:
* C-h v lexical-binding
* C-h f defvar
* C-h f lambda
* C-h f lexical-let
# 10 examples with lexical-binding, lambda, defun, let, lexical-let, setq, defvar
example 1
(setq lexical-binding nil)
(lambda (x) (* x x)) ; (lambda (x) (* x x))
example 2
(setq lexical-binding t)
(lambda (x) (* x x)) ; (closure (t) (x) (* x x))
example 3
(setq lexical-binding nil)
(let ((x 1)) (lambda (y) (+ x y)))
;; (lambda (y) (+ x y))
example 4
(setq lexical-binding t)
(let ((x 1)) (lambda (y) (+ x y)))
;; (closure ((x . 1) t) (y) (+ x y))
example 5
(setq lexical-binding t)
(let ((n 1)) (defun n+ (y) (+ n y)))
(n+ 1) ; 2
(let ((n -10)) (n+ 1)) ; 2
example 6
(setq lexical-binding nil)
(let ((n 1)) (defun n+ (y) (+ n y)))
(should-error (n+ 1) :type 'void-variable) ; (void-variable n)
(let ((n -10)) (n+ 1)) ; -9
example 7
(setq lexical-binding nil)
(lexical-let ((n 1)) (defun n+ (y) (+ n y)))
(n+ 1) ; 2
(let ((n -10)) (n+ 1)) ; 2
example 8
(setq lexical-binding t)
(setq xx 10)
(let ((xx 1)) (defun xx+ (y) (+ xx y)))
(xx+ 1) ; 2
(let ((x -10)) (xx+ 1)) ; 2
example 9
(setq lexical-binding t)
(defvar xxx 10)
(let ((xxx 1)) (defun xxx+ (y) (+ xxx y)))
(xxx+ 1) ; 11
(let ((xxx -10)) (xxx+ 1)) ; -9
example 10
(setq lexical-binding t)
(let ((xxxx 1)) (defun xxxx+ (y) (+ y xxxx)))
(defvar xxxx 10)
(xxxx+ 1) ; 11
(let ((xxxx -10)) (xxxx+ 1)) ; -9
# advanced example using lambda, let, dolist, defun
Evaluating the following forms with lexical binding:
(setq lexical-binding t)
(defun call-f (f x)
`(:x-in-call-f ,x
:result-of-f ,(funcall f x)
:type-of-f ,(car f)
:env-of-f ,(and (eq (car f) 'closure) (cadr f))))
(dolist (x '(1 2 3))
(let ((f (lambda (y) `(:x-in-f ,x :y ,y))))
(message "%S" (append `(:x-in-dolist ,x) (call-f f -1)))))
prints out the following into the message buffer:
(:x-in-dolist 1
:x-in-call-f -1
:result-of-f (:x-in-f 1 :y -1)
:type-of-f closure
:env-of-f ((--dolist-tail-- 1 2 3) t))
(:x-in-dolist 2
:x-in-call-f -1
:result-of-f (:x-in-f 2 :y -1)
:type-of-f closure
:env-of-f ((--dolist-tail-- 2 3) t))
(:x-in-dolist 3
:x-in-call-f -1
:result-of-f (:x-in-f 3 :y -1)
:type-of-f closure
:env-of-f ((--dolist-tail-- 3) t))
Evaluating the following forms with dynamic binding:
(setq lexical-binding nil)
(defun call-f (f x)
`(:x-in-call-f ,x
:result-of-f ,(funcall f x)
:type-of-f ,(car f)
:env-of-f ,(and (eq (car f) 'closure) (cadr f))))
(dolist (x '(1 2 3))
(let ((f (lambda (y) `(:x-in-f ,x :y ,y))))
(message "%S" (append `(:x-in-dolist ,x) (call-f f -1)))))
prints out the following into the message buffer:
(:x-in-dolist 1
:x-in-call-f -1
:result-of-f (:x-in-f -1 :y -1)
:type-of-f lambda
:env-of-f nil)
(:x-in-dolist 2
:x-in-call-f -1
:result-of-f (:x-in-f -1 :y -1)
:type-of-f lambda
:env-of-f nil)
(:x-in-dolist 3
:x-in-call-f -1
:result-of-f (:x-in-f -1 :y -1)
:type-of-f lambda
:env-of-f nil)