gpt4 book ai didi

emacs - emacs lisp 中词法绑定(bind)和 defvar 之间的奇怪交互

转载 作者:太空宇宙 更新时间:2023-11-03 18:36:51 24 4
gpt4 key购买 nike

下面的 emacs lisp 文件是关于当 Alice 在她的 init 文件中使用词法绑定(bind)的局部变量 foo 并且 Bob 将 foo 定义为全局特殊变量时会发生什么defvar 在他的 init 文件中,Alice 借用了 Bob 的部分 init 文件代码到她自己的 init 文件中,不知道 foo 会变成特殊的。

;; -*- lexical-binding: t; -*-
;; Alice init file

;; Alice defining alice-multiplier
(defun alice-multiplier-1 (foo)
(lambda (n) (* n foo)))
(defun alice-multiplier-2 (num)
(let ((foo num))
(lambda (n) (* n foo))))

;; Alice using alice-multiplier
(print
(list
:R1 (mapcar (alice-multiplier-1 10) (list 1 2 3))
:R2 (mapcar (alice-multiplier-2 10) (list 1 2 3))))

;; from Bob's code
;; ...
(defvar foo 1000)
;; ...

;; Alice using alice-multiplier
(print
(list
:R3 (mapcar (alice-multiplier-1 10) (list 1 2 3))
:R4 (mapcar (alice-multiplier-2 10) (list 1 2 3))))

输出:

(:R1 (10 20 30) :R2 (10 20 30))

(:R3 (10 20 30) :R4 (1000 2000 3000))

结果R1和R2如我所料。结果 R4 与 defvar 文档一致,尽管 Alice 可能会感到惊讶,除非她阅读 Bob 的代码。

  1. 我发现 R3 令人惊讶。为什么R3会这样?

  2. 说到 R4,Alice 可以做些什么来保护她的 foo 不被其他人变成特殊的?例如,foo 可能是她在 init 文件或她的 emacs 包之一中使用的词法局部变量,而 (defvar foo "something") 可能在某些她碰巧使用的包,或者 foo 可能是 future 版本的 Emacs 引入的新的特殊变量名称之一。 Alice 是否可以在她的文件中添加一些内容来对 Emacs 说“在这个文件中,foo 应该始终是词法的,即使来自外部的某些代码碰巧使用了同名的特殊变量”?

最佳答案

发生了什么

从“理论”(Scheme/Common Lisp)的角度来看,一旦您启用词法绑定(bind),出于所有实际目的 alice-multiplier-1alice-multiplier- 2 相同。它们行为上的任何差异都是 Emacs Lisp 中的一个错误,应该这样报告。

已编译

如果您将代码(即 2 个 defun;; -*- lexical-binding: t; -*- 行)放入文件中, emacs-list-byte-compile-and-load 它,然后你可以通过评估这 4 种形式来测试我的说法:

(disassemble 'alice-multiplier-1)
(disassemble 'alice-multiplier-2)
(disassemble (alice-multiplier-1 10))
(disassemble (alice-multiplier-2 10))

您会看到 3 和 4 是相同的,而 1 和 2 有一条指令不同(这应该作为错误报告给 Emacs 维护者,但不会影响行为)。

请注意,没有任何反汇编提及 foo,这意味着 defvar不会影响它们的行为。

一切都很好!

解释

确实,您看到的行为是不正确的; defvar 之后的正确结果是

(:R1 (10000 20000 30000) :R2 (10000 20000 30000))

report this to the emacs maintainers .

不同???

是的,defvar 确实(并且应该!)影响解释代码的行为,但不会(并且不应该!)影响已编译代码的行为。

你应该做什么

没有办法“保护”你的 foo 不被其他人宣称为 special - 除非在“你的”符号前加上 alice-.

但是,如果您使用 alice-multiplier-1 定义对文件进行字节编译,编译后的文件甚至不包含 foo,因此 的 future 声明>foo 不会影响你。

关于emacs - emacs lisp 中词法绑定(bind)和 defvar 之间的奇怪交互,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17400556/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com