;;;; Evaluating the same code under dynamic bindings (Emacs' default) ;;;; and lexical bindings. Make sure you understand this example. ; From Emacs manual: ; "Dynamic binding is implemented in Emacs Lisp in a simple ; way. Each symbol has a value cell, which specifies its current ; dynamic value (or absence of value). See Symbol Components. When ; a symbol is given a dynamic local binding, Emacs records the ; contents of the value cell (or absence thereof) in a stack, and ; stores the new local value in the value cell. When the binding ; construct finishes executing, Emacs pops the old value off the ; stack, and puts it in the value cell." ((lambda (x) (let ((makeInc (lambda (inc) (lambda (x) (+ x inc))))) (let ((inc1 (funcall makeInc 1)) (inc5 (funcall makeInc 5))) (+ (funcall inc1 x) (funcall inc5 x))))) 3) ; error message pasted from *Backtrace* buffer: ;; this is how Elisp evaluation evaluates the expressions in order, ;; bottom first. Debugger entered--Lisp error: (void-variable inc) (+ x inc) (lambda (x) (+ x inc))(3) funcall((lambda (x) (+ x inc)) 3) (+ (funcall inc1 x) (funcall inc5 x)) (let ((inc1 (funcall makeInc 1)) (inc5 (funcall makeInc 5))) (+ (funcall inc1 x) (funcall inc5 x))) (let ((makeInc (function (lambda (inc) (function (lambda (x) (+ x inc))))))) (let ((inc1 (funcall makeInc 1)) (inc5 (funcall makeInc 5))) (+ (funcall inc1 x) (funcall inc5 x)))) (lambda (x) (let ((makeInc (function (lambda (inc) (function (lambda ... ...)))))) (let ((inc1 (funcall makeInc 1)) (inc5 (funcall makeInc 5))) (+ (funcall inc1 x) (funcall inc5 x)))))(3) eval(((lambda (x) (let ((makeInc (function (lambda (inc) (function ...))))) (let ((inc1 (funcall makeInc 1)) (inc5 (funcall makeInc 5))) (+ (funcall inc1 x) (funcall inc5 x))))) 3) nil) eval-last-sexp-1(t) eval-last-sexp(t) eval-print-last-sexp(nil) call-interactively(eval-print-last-sexp nil nil) command-execute(eval-print-last-sexp) ;; Each variable is looked up by name right when it's evaluated. ;; So (+ x inc) and anything containing it is doomed to fail unless inc ;; is bound when evaluated---which it is not, under dynamic scoping. ;;;; Under lexical bindings, the picture is different: (setq lexical-binding t) t ((lambda (x) (let ((makeInc (lambda (inc) (lambda (x) (+ x inc))))) (let ((inc1 (funcall makeInc 1)) (inc5 (funcall makeInc 5))) (+ (funcall inc1 x) (funcall inc5 x))))) 3) ;=> 12 ;; Recall from the bytecode examples that inc and x would have been ;; cells copied into the closures, and then numbered and nameless slots ;; on the stack when copied there by compiled code---not variables to ;; be looked up by name!