在 .emacs 中开启词法绑定的作用?

Reported as bug#64272.


我尝试了:

 ;;; ~/.emacs  -*- lexical-binding: t; -*-
(minibuffer-message "-*- %s -*-" lexical-binding)

启动时消息显示 nil:

也就是说 .emacs 中的代码都不是在词法环境下求值的?

但我看到很多人的 .emacs 都 (使用 file local variable 的方式) 开启了 lexical-binding, 请问这样做的目的是什么?

你的测试方法有问题,这样测出来的是 当前 buffer 的 lexical-binding 状态,和用来读取配置文件的无关

靠谱的方法是在 dot emacs 里定义

(let ((x 1)) (setq foo (lambda () x)))
(message (funcall foo))

思考题:

为什么要用 file local variable,而不是直接在文件里写

(setq lexical-binding t)

来开启词法作用

没有什么用的提示:这其实和 TeX 修改 catcode 是异曲同工的

有用的提示:思考题的答案和主题问题的导致原因没什么关系

是有问题, 我本地的文件是

 ;;; ~/.emacs.d/init.el  -*- lexical-binding: t; -*-
^ space here

删掉这个空格就识别出来了… 可是文档没说不能加空格啊.


             ^ typo here

其实直接

(message "%s" foo)

就好了, 词法环境下 fooclosure 打头, 而不是 lambda.


相当于 let 绑定吧.

不了解 TeX.

那就是 lisp_file_lexically_bound_p 的 bug,我去报了。

和 byte compiler 有关,你自已试吧,我去写 bug report 了。

所以这个问题看上去是个误会。

扯开话题:我还有另外一个问题 custom-set-variablesletrec 之间似乎有冲突。感兴趣的话请看一下。谢谢佬。

你应该用

(custom-set-variables
 `(post-self-insert-hook ,`(,@(when (boundp 'post-self-insert-hook)
                               post-self-insert-hook)
                           ,(letrec ...))))

和 letrec 无关

你应该看我问题描述后面怎么写的,一层 backquote 就可以了。另外我的问题是,为什么原来那种写法不行。

一层不可以,不行就是不行,和 letrec 无关。

不是,你有没有试过我问题中第三段代码。那个是一层的。

那个是可以,但还是和 letrec 无关。

你自己看 backquote 怎么展开就知道了

你用 let 试一下,没有问题的。所以问题很可能和 letrec 有关。我当然知道 backquote 是怎么展开的。

(custom-set-variables
 '(post-self-insert-hook `(,@(when (boundp 'post-self-insert-hook)
                               post-self-insert-hook)
                           ,(let (_ (lambda ()
                                             (message ":P")
                                             (remove-hook 'post-self-insert-hook _))))
                                 _)))

Error setting post-self-insert-hook: (error `let’ bindings can have only one value-form lambda nil (message :P) (remove-hook 'post-self-insert-hook _))

怎么可以了?

你要是知道就不会有这问題了

你是这样测试的吗?

你怎么能在 let 里面用 remove-hook 呢,这不肯定不行吗。要不先看一下 letrec 的用法?

结论,你的括号数错了

然而并没有数错。或者说我代码缺注释,导致你没理解我的意思

麻了,看了半天才看懂你什么意思。

你是说你这么写了

(custom-set-variables
 '(post-self-insert-hook `(,@(when (boundp 'post-self-insert-hook)
                                  post-self-insert-hook)
                              ,(letrec ((x (lambda ()
                                             (message ":P")
                                             (remove-hook 'post-self-insert-hook x))))
                                 x))))

然后每按一个键会运行一次这个 closure。

运行这个 closure 才会报 Symbol’s value as variable is void

还 self explanatory? 故意把关健信息省略是吧

我只想运行一次。我都用letrec了,知道letrec的人肯定知道我想干什么。为什么会认为我想要每次按键都运行呢?

很简单,custom-set-variables 不会用词法作用域 eval 参数。

知道仲p

我知道不会,所以我试过加 let 绑定,开启词法作用域。就加在letrec外面那一层。为什么这样也不行?