在 Emacs Lisp 中分配给自由变量有什么危险?
What are the dangers of assigning to a free variable in Emacs Lisp?
在代码中添加 (setq foo 1)
而没有使用 defvar
定义变量 foo
将导致 Emacs 字节编译器生成以下警告:
assignment to free variable `foo'
在没有预先定义的情况下分配给这样的自由变量有什么危险?
Emacs Lisp 默认使用Dynamic Binding,所以当你写
(defun my-fun-1 (...)
...
(setq foo 1)
...)
并收到警告,代码相当于在 defun
之前添加 (defvar foo)
。
这意味着上面的my-fun-1
与
共享foo
的值
(defun maybe-start-ww3 ()
(when (= 1 foo)
(launch-missiles)))
这并不总是坏事;许多 ELisp 遗留代码使用这样的全局变量来传递状态。然而,这是一个 非常 糟糕的风格,如果你在两个不相关的地方使用相同的变量名(例如 date
)用于这些目的,后果可能无法预测。
总之,如果你在单个地方使用自由变量,没有理由不绑定它。
如果您使用它来传递状态,您应该 defvar
它并使用不太可能被其他人使用的长名称 - 您应该重构您的代码以避免这种情况。
在代码中添加 (setq foo 1)
而没有使用 defvar
定义变量 foo
将导致 Emacs 字节编译器生成以下警告:
assignment to free variable `foo'
在没有预先定义的情况下分配给这样的自由变量有什么危险?
Emacs Lisp 默认使用Dynamic Binding,所以当你写
(defun my-fun-1 (...)
...
(setq foo 1)
...)
并收到警告,代码相当于在 defun
之前添加 (defvar foo)
。
这意味着上面的my-fun-1
与
foo
的值
(defun maybe-start-ww3 ()
(when (= 1 foo)
(launch-missiles)))
这并不总是坏事;许多 ELisp 遗留代码使用这样的全局变量来传递状态。然而,这是一个 非常 糟糕的风格,如果你在两个不相关的地方使用相同的变量名(例如 date
)用于这些目的,后果可能无法预测。
总之,如果你在单个地方使用自由变量,没有理由不绑定它。
如果您使用它来传递状态,您应该 defvar
它并使用不太可能被其他人使用的长名称 - 您应该重构您的代码以避免这种情况。