6

I've seen ;;; -*- lexical-binding: t; -*- at the top of a file and (setq lexical-binding t) as how to turn on lexical binding for elisp code, but is there a way to tell Emacs to simply always do lexical binding, i.e., in your init file? From what I've seen, my guess would be it's a buffer-only option. Also, how can lexical binding be turned on in an org file? Does each babel emacs lisp code block have to specify (setq lexical-binding t)? BTW, putting ;;; -*- lexical-binding: t; -*- is not dealt with well on an export to HTML, etc. Using version 26.1.

1 Answer 1

11

Elisp

AFAIK the only two reliable ways for using lexical binding in Elisp files are:

  1. Setting the buffer-local variable lexical-binding as file-local variable at the beginning of the Elisp file with
    ;;; -*- lexical-binding: t; -*-

  2. Using eval with non-nil LEXICAL argument. (LEXICAL can be t or the lexical environment to be used)

Motivation for that behavior is that a global setting would potentially break your emacs configuration. Lexical binding in Elisp is a relatively new feature and older packages can rely on dynamic binding. See the difference in the behavior of lex-p below for both variants of binding.

Org-mode

I don't know where you got (setq lexical-binding t) from. That just does not work as the following Org source block shows:

#+BEGIN_SRC emacs-lisp
(setq lexical-binding t)
(defun lex-p ()
  "Return t if lexical binding is in effect."
  (let (lex
    _lex-p)
    (let ((lex t))
      (setq _lex-p
        (lambda ()
          lex)))
    (funcall _lex-p)))

(if (lex-p) "Yes" "No")
#+END_SRC

#+RESULTS:
: No

Nevertheless there is the header argument :lexical for Org source block that just does what you want:

#+BEGIN_SRC emacs-lisp :lexical t
(defun lex-p ()
  "Return t if lexical binding is in effect."
  (let (lex
    _lex-p)
    (let ((lex t))
      (setq _lex-p
        (lambda ()
          lex)))
    (funcall _lex-p)))

(if (lex-p) "Yes" "No")
#+END_SRC

#+RESULTS:
: Yes

You can set that header argument file global by the header-args property:

#+PROPERTY: header-args:emacs-lisp :lexical t

#+BEGIN_SRC emacs-lisp
(defun lex-p ()
  "Return t if lexical binding is in effect."
  (let (lex
    _lex-p)
    (let ((lex t))
      (setq _lex-p
        (lambda ()
          lex)))
    (funcall _lex-p)))

(if (lex-p) "Yes" "No")
#+END_SRC

#+RESULTS:
: Yes

#+BEGIN_SRC emacs-lisp
(if (lex-p) "Foo" "Bar")
#+END_SRC

#+RESULTS:
: Foo
9
  • Thanks, this makes sense. Still, in the second code block I see #+BEGIN_SRC emacs-lisp :lexical t but the next line is (setq lexical-binding t). You say above the second is ineffective? What was your thinking there?
    – 147pm
    Mar 29, 2019 at 3:37
  • @147pm Thanks for the note. The presence of (setq lexical-binding t) in the second block was a copy-paste error. I have corrected it.
    – Tobias
    Mar 29, 2019 at 3:47
  • (setq lexical-binding t) is needed to use lexical-binding in *scratch*.
    – npostavs
    Mar 29, 2019 at 4:16
  • @npostavs if I put the code from the first code block into *scratch*, change the (if (lex-p) "Yes" "No") into (message (if (lex-p) "Yes" "No")) and evaluate the buffer with M-x eval-buffer I get the message "No". On the other hand if I put the stuff from the second source block into the scratch buffer wrap the last form into message and wrap everything by a (eval '(progn ...) t) I get a "Yes".
    – Tobias
    Mar 29, 2019 at 4:52
  • @npostavs Even more important: If I put the stuff from second source block into *scratch* with the last form wrapped in (message ...), insert ;; -*- lexical-binding: t -*- at the beginning of the buffer, and run M-x eval-buffer I get a "Yes".
    – Tobias
    Mar 29, 2019 at 5:03

Your Answer

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

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