请问 ;; -*- lexical-binding: t; -*- 作用范围

在一个 .el 文件中

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

必须写在文件开头第一行才能生效吗?
如果写在文件中间的位置,是不是只影响此位置到文件末尾的内容?

或者说当文件中某一位置出现它时,它的影响范围可以达到文件的哪个位置?

Emacs 的 file-local 变量可以写在文件的开头或者结尾,写在开头的话就是这种形式:

;;; -*- var1:value1;var2:value2;... -*-

想要让当前 elisp 文件默认使用词法作用域,把 lexical-binding:t 放在开头是最好的唯一标准的做法。如果要放在文件末尾的话,得用如下格式:

;; Local Variables:
;; variable: value
;; End:

有个专门的函数可以添加 file-local 变量到末尾: add-file-local-variable。把 lexical-binding 放在文件末尾不是一种比较好的做法,原因可以参考: 求助:启动emacs出现“:no_entry: Warning (files): : ‘lexical-binding’ at end of file unreliable”警告

如果写在文件中间的位置,是不是只影响此位置到文件末尾的内容?

答案是不能写在中间,只能是开头或结尾,且必须满足格式要求,而且结尾是不好的做法会出现非预期行为

或者说当文件中某一位置出现它时,它的影响范围可以达到文件的哪个位置?

lexical-binding 来说,它的效果是全局的,其他变量应该也是Emacs 解释器不会查看 lexical-binding 以外的变量。

2 个赞

解答得好详细。:+1:
明白啦。 :blush:感谢!

1 个赞

注意,用 load 加载没有编译的文件时这个变量必须写在文件中第一个換行符前面(即第一行)才能生效,并且文件的开头必须是注释 ; 或者 #!),而且前面不应该有如空格等其他字符。因为 emacs 解释器代码没法在读到文件后面再切换 lexical binding,并且本身除了编程成在文件开头检查 lexical binding 变量外,对注释内容是完全忽略的。如果写在文件结尾,这种情况是不会生效的。这是一个已知 bug,之前在论坛里通过 @Shynur 发现的 在 .emacs 中开启词法绑定的作用? - #4,来自 LdBeth

https://mail.gnu.org/archive/html/bug-gnu-emacs/2023-06/msg01331.html

只有在 byte compile 时,因为会把整个文件读取到 buffer 里写在后面的这个变量才能生效。

这个 bug 最后没有完全解决,因为需要重新设计解释器,只能加个编译器警告了事,但是实际上会影响的是解释器

举几个例子,这些写法虽然在第一行,而且 hack-local-variables 能认出来,但对于用 lisp_file_lexically_bound_p 的解釋器也是不行的

(let ((y 12)) (defun foo (x) (setq y x))) ;; -*- lexical-binding: t; -*-
(let ((y 12)) (defun foo (x) "-*- lexical-binding: t; -*-" (setq y x)))

然后点名批评 @include-yy

这个不是应该忽略的问题,只是实在没办法挡住头脑奇妙的人用不标准的写法,才勉强实现成 warning。

2 个赞

感谢指正

就 lexical-binding 来说,确实要求应该更加严格一点,而且这个帖子的主题是 lexical-binding 的使用。

再补充个函数,用 elisp-enable-lexical-binding 可以在 emacs-lisp buffer 中插入这一串 ;; -*- lexical-binding:t -*-,不用自己敲

1 个赞