1. setq lexical-binding失效
从Emacs 24开始,Emacs可以启用变量的lexical binding模式,
Emacs Lisp Reference:11.9.4 Using Lexical Binding中提到,
When loading an Emacs Lisp file or evaluating a Lisp buffer, lexical binding is enabled if the buffer-local variable
lexical-binding
is non-nil
:
—— Variable:
lexical-binding
If this buffer-local variable is non-nil
, Emacs Lisp files and buffers are evaluated using lexical binding instead of dynamic binding. (However, special variables are still dynamically bound; see below.) Ifnil
, dynamic binding is used for all local variables. This variable is typically set for a whole Emacs Lisp file, as a file local variable.
Note that unlike other such variables, this one must be set in the first line of a file.
然而,以下代码,M-x eval-buffer
之后,仍然会报错,
仍然使用了变量的dynamic binding模式,
(setq lexical-binding t)
(setq test (let ((foo "bar"))
(lambda ()
foo)))
(let ((foo "something-else"))
(funcall test)) ; "something-else"
(funcall test) ; Error! Symbol’s value as variable is void: foo
注:
(1)依次对每个表达式使用:M-x eval-last-sexp
(快捷键:C-x C-e
),
是不会报错的,确实启用了词法作用域。
但是使用M-x eval-buffer
求值整个buffer,或者在其他文件中load
本文件时,就会报错。
(2)M-x eval-buffer
,可以简写为M-x ev-b
。
2. 解决方案
将文件的第一行改成:; -*- lexical-binding: t -*-
Emacs Version: 25.2
例如:M-x eval-buffer
和load
都不报错,启用了词法作用域。
; -*- lexical-binding: t -*-
(setq test (let ((foo "bar"))
(lambda ()
foo)))
(let ((foo "something-else"))
(funcall test)) ; "bar"
(funcall test) ; "bar"
注:
(1); -*- lexical-binding: t -*-
必须位于文件或者buffer的第一行。
(2)这条指令是以注释的方式存在的,在-*- ... -*-
外面可以写任何其他注释,此外多个“;
”肯定也是可以的“;;
”,例如:;; 123 -*- lexical-binding: t -*- 456
。
3. File Variables
-*- mode: modename; var: value; ... -*-
,
类似这样的写法,实际上是在Emacs中指定了File Variables。
GNU Emacs manual: 51.2.4.1 Specifying File Variables中指出,
There are two ways to specify file local variable values: in the first line, or with a local variables list.
Here's how to specify them in the first line:
-*- mode: modename; var: value; ... -*-
A local variables list starts with a line containing the string ‘Local Variables:’, and ends with a line containing the string ‘End:’. In between come the variable names and values, one set per line, like this:
/* Local Variables: */
/* mode: c */
/* comment-column: 0 */
/* End: */
参考
GNU Emacs manual
GNU Emacs Lisp Reference Manual
Emacs Wiki: Lexical binding