如果在不使用defvar
定义变量foo
的情况下,将(setq foo 1)
添加到代码中,将会导致Emacs字节编译器生成以下警告:
assignment to free variable `foo'
没有对自由变量进行先前定义而分配给它的危险是什么?
Emacs Lisp默认使用动态绑定,因此当您编写以下代码时:
(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
它,并使用一个长名称,不太可能被他人使用,并且您应该重构您的代码以避免使用该变量。
defvar
将会增加一份重要的文档说明。 - sdsdefvar
不会评估给定的符号,这使得在此上下文中使用它不可能。 - Andrzej Pronobisgensym
和declare
等)。请提出一个单独的问题。 - sdsdefvar
不会对其给定的符号进行求值,但你也不需要这样做,因为你的宏可以返回形式为(progn (defvar <foo>) ...)
的内容,这样你就可以构建 defvar,在宏展开的代码运行时执行一次。 - Stefan