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 Answers
Elisp
AFAIK the only two reliable ways for using lexical binding in Elisp files are:
Setting the buffer-local variable
lexical-binding
as file-local variable at the beginning of the Elisp file with
;;; -*- lexical-binding: t; -*-
Using
eval
with non-nilLEXICAL
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

- 32,569
- 1
- 34
- 75
-
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 '19 at 03: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 '19 at 03:47
-
`(setq lexical-binding t)` is needed to use lexical-binding in `*scratch*`. – npostavs Mar 29 '19 at 04: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 '19 at 04: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 '19 at 05:03
-
Hmm, okay, I never `eval-buffer` in `*scratch*`. I was thinking of `eval-last-sexp` (`C-x C-e`) or `eval-defun` (`C-M-x`). – npostavs Mar 29 '19 at 10:05
-
@npostavs I can imagine that `eval-last-sexp` works since `elisp--eval-last-sexp` calls `eval` with `lexical-binding` as its `LEXICAL` argument. interestingly `eval-region` respects the current buffer-local value of `lexical-binding` while `eval-buffer` does not. Maybe the motivation is that `eval-buffer` can "look" at the beginning of the buffer while `eval-region` should not. – Tobias Mar 29 '19 at 11:00
-
I have just discovered `auto-insert-mode` via [this reddit post](https://www.reddit.com/r/emacs/comments/7y000a/how_to_add_lexicalbinding_t_to_every_new_elisp/). It might be handy to know about, very convenient! For me the behavior of just activating `auto-insert-mode` is fine enough, no need to use the hooks etc. as mentioned in the (currently) most popular comment there... – dalanicolai Aug 19 '22 at 13:35
-
About the scratch buffer, if the buffer is in `lisp-interaction-mode` then, as mentioned in the docs [here](https://www.gnu.org/software/emacs/manual/html_node/elisp/Using-Lexical-Binding.html), `lexical-binding` is `t`, in any other mode AFAIK, it is `nil`. – dalanicolai Aug 19 '22 at 13:42