Lexical eval in emacs24
elisp, emacs, emacs24
Solution
Since lexical binding breaks much existing elisp code, it is an opt-in feature.
lexical scoping can best be understood with a simple example:
(defun some-func (callback)
(let ((a 5))
(funcall callback)))
(let ((a 3))
(some-func (lambda () a)))
Under most languages, this would return 3 since the `a` in `some-func` doesn't seem visible from the bottom form. However, in emacs before 24 or without lexical scope this program returns 5.
This has led to many unexpected surprises and subtle and often hidden bugs between interacting functions; to fix this emacs 24 introduced lexical scoping, but as mentioned previously, is backwards compatible.
The mechanism to opt-in to dynamic scoping is either the file variable `lexical-binding` (which turns it on per source file) or as the option you see to `eval`
So if we rewrite the example to use `eval`:
(eval '(let ((a 3))
(some-func (lambda () a))) nil) ; => 5
(eval '(let ((a 3))
(some-func (lambda () a))) t) ; => 3
In your example, what is making the difference is not whether the code inside `eval` is dynamically scoped, but whether the code surrounding it is. Variable binding is what is affected by lexical scoping, not variable lookup. I'm not completely certain of `eval`'s semantics here, but what seems to be happening (and what makes the most sense) is `eval` evaluates the expression in an entirely new lexical context. So the outer lexical scope is hidden from the inside of `eval`, but the dynamic scope is still visible (so the lookup succeeds when the file is dynamically scoped, but not otherwise).
Problem
Can anybody explain me how `eval` works with emacs24? From `eval` description: ``` eval is a built-in function in `C source code'. (eval FORM &optional LEXICAL) Evaluate FORM and return its value. If LEXICAL is t, evaluate using lexical scoping. ``` Does that mean, that something like this should work? ``` (setq lexical-binding t) (let ((myvarr 42)) (eval 'myvarr t)) ; (void-variable myvarr) ``` Update: ``` (setq lexical-binding nil) ;; => nil (let ((myvarr 42)) (eval 'myvarr)) ;; => 42 (#o52, #x2a, ?*) (setq lexical-binding t) ;; => t (let ((myvarr 42)) (eval 'myvarr)) ;; Debugger entered--Lisp error: (void-variable myvarr) ;; eval(myvarr) ;; (let ((myvarr 42)) (eval (quote myvarr))) ;; (progn (let ((myvarr 42)) (eval (quote myvarr)))) ;; eval((progn (let ((myvarr 42)) (eval (quote myvarr)))) t) ;; eval-last-sexp-1((4)) ;; eval-last-sexp((4)) ;; call-interactively(eval-last-sexp nil nil) ;; call-last-kbd-macro(nil kmacro-loop-setup-function) ;; kmacro-call-macro(nil nil) ;; kmacro-end-or-call-macro(nil) ;; call-interactively(kmacro-end-or-call-macro nil nil) (ignore-errors (let ((myvarr 42)) (eval 'myvarr))) ;; => nil (setq lexical-binding nil) ;; => nil (eval (let ((myvarr 42)) (eval 'myvarr)) t) ;; => 42 (eval '(let ((myvarr 42)) (eval 'myvarr)) t) ;; Debugger entered--Lisp error: (void-variable myvarr) ;; eval(myvarr) ;; (let ((myvarr 42)) (eval (quote myvarr))) ;; eval((let ((myvarr 42)) (eval (quote myvarr))) t) ;; eval((eval (quote (let ((myvarr 42)) (eval (quote myvarr)))) t) nil) ;; eval-last-sexp-1((4)) ;; eval-last-sexp((4)) ;; call-interactively(eval-last-sexp nil nil) ``` Emacs version: `GNU Emacs 24.1.1 (i386-mingw-nt6.1.7600) of 2012-06-10 on MARVIN`