;; -*- 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 的代码。
我觉得 R3 很令人惊讶。为什么 R3 是这样的?
说到 R4,Alice 能做些什么来保护她的
foo
不被他人变成特殊变量呢?例如,foo
可能是她在初始化文件或其中一个 Emacs 包中使用的词法局部变量,而(defvar foo "something")
可能在她使用的某些包中出现,或者foo
可能是未来版本的 Emacs 引入的新的特殊变量名称之一。Alice 能在她的文件中加入什么东西告诉 Emacs,“在这个文件中,即使外部代码使用了同名的特殊变量,foo 应该始终是词法变量”吗?
.emacs
文件中,而不是来自文件外部。 - Joshua Taylorsuperdired
,其中 defvarsfoo
,而 Mallory 可能会安装两个包superdired
和supercalc
,后者是由 Alice 编写的,提供类似于alice-multiplier
的函数。当 Mallory 在一个 superdired 缓冲区中进行某些操作,然后在另一个不相关的任务中使用alice-multiplier
时,如果 Alice 将alice-multiplier
编写为alice-multiplier-2
,则 Mallory 将看到 R4。 - Jisang Yoo