lexical-binding nil ;;----- trying old scope-test first: (let ((y 7)) (defun scope-test (x) (list x y))) scope-test (scope-test 1) ;; fails (let ((y 5)) (scope-test 2)) (2 5) ;;----- as expected. Now let's do another, first with dynamic, then lexical: lexical-binding nil (defun make-multiplier (x) (lambda (y) (* x y))) make-multiplier (disassemble (byte-compile 'make-multiplier)) nil --------- Pasted from another buffer: --------- byte code: args: (x) 0 constant args: (y) 0 varref x ; <-- look up value of x, and push on top of the stack 1 varref y ; <-- same for y 2 mult ; <-- multiply the two values on top of the stack, put result on top 3 return ; <--- the value is on top of the stack 1 return ----------------------------------------------- (setq x 10) 10 (make-multiplier 5) ; the passed-in argument will be ignored, ; the resulting lambda just looks up "x" and "y" whenever it's called, ; as the bytecode above shows. (lambda (y) (* x y)) (funcall (make-multiplier 5) 2) 20 (setq x 4) 4 (funcall (make-multiplier 5) 2) 8 ;;;;---- Now to switch to lexical binding: ---- (setq lexical-binding t) t (defun make-multiplier (x) (lambda (y) (* x y))) make-multiplier (make-multiplier 5) ;; this is a closure; it captures x as it's created, and will keep it (closure ((x . 5) t) (y) (* x y)) (disassemble (byte-compile 'make-multiplier)) ;; completely different bytecode nil --------- Pasted from another buffer: --------- byte code: doc: ... args: 257 0 constant make-byte-code 1 constant 257 2 constant "\300_\207" 3 constant vconcat 4 constant vector 5 stack-ref 5 6 call 1 7 constant [] 8 call 2 9 constant 3 10 constant "\n\n(fn Y)" 11 call 5 12 return ----------------------------------------------- (setq x 10) 10 (make-multiplier 5) ; now it's compiled #[257 "\300_\207" [5] 3 " (fn Y)"] (funcall (make-multiplier 5) 2) ;; using the captured x, not the global one! 10 ;; <-- was 20 (setq x 4) 4 (funcall (make-multiplier 5) 2) ;; ditto. It's a closure. 10 ;; <-- was 8