2

Suppose you save the following code to some file test.el and then do load-file test.el

;;; -*- lexical-binding: t -*-

(let ((closure-vbl 0))
  (defun tst ()
    (eval 'closure-vbl)))

(tst)

You get the error tst: Symbol's value as variable is void: closure-vbl. (Replacing (eval 'closure-vbl) with (symbol-function 'closure-vbl) gives the same error.)

Why is this? I don't understand what is wrong with the above code? Am I miunderstanding some property of emacs closures? Or are they simply not developed enough to deal with non-trivial situations.

1 Answer 1

4

There's a few pitfalls here:

  • Using eval with lexical-binding will fail unless you pass it an alist environment argument holding the bindings in question (see F1 f eval)
  • Looking up symbol slots only behaves correctly with dynamic scoping, if you attempt it despite this, you'll get the global value (see F1 f symbol-value)

FWIW, this is what I'd call the straight-forward use:

;; -*- lexical-binding: t; -*-

(let ((closure-variable 0))
  (defun test ()
    closure-variable))

(test)
2
  • 1
    Is there any way to get the lexical environment in a function? More generally, is it ever possible to indirectly refer to a lexically-scoped variable? Something like the following also fails: (defun tst3 (vbl) (eval 'vbl t)) (Here, I've tried using the LEXICAL flag on eval but it doesn't seem to help.) Jan 24, 2017 at 8:52
  • "s it ever possible to indirectly refer to a lexically-scoped variable?" - is basically asking if is it possible to refer to a lexically-scoped variable outside of its lexical scope. No, it's not, as that would defeat the whole point of lexical binding in the first place (well, unless you access the internal details of a closure as described in an answer here).
    – npostavs
    Oct 14, 2019 at 3:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.