Get rid of “reference to free variable” byte-compilation warnings

强颜欢笑 提交于 2019-11-28 21:04:17

The official way to do what you want is (defvar foo-state). Note the absence of a second argument. Note also that such a declaration only applies to the file where it is found (or to the scope in which it is found, if it's used inside a function).

lunaryorn

Declare the variable with defvar. There is no other way to remove the warning, and it is really considered good practice.

Your intention to keep the symbol table uncluttered is worthy, but you are not actually doing so. I think you have misunderstood the semantics of variable bindings in Emacs Lisp, since you seem to believe that by not declaring it foo-state will be unbound in any buffer not using foo-mode. That is not the case.

In Emacs Lisp names (aka symbols) are global. As soon as foo-state is evaluated the first time, the runtime creates a new symbol object for foo-state and puts this into the global symbol table (aka obarray). There are no local symbol tables, so it does not matter where foo-state is evaluated and how, foo-state refers to the same symbol object at any place (see Creating Symbols).

Each symbol object consists of components (aka cells), one of which is the variable cell (see Symbol components). setq modifies the current binding of the system, on top-level without lexical binding this effectively changes the variable cell of the symbol object, thus the global value of the variable. Again, it does not matter where setq is evaluated. Actually if some bar-mode evaluated (setq foo-state "bar"), foo-state would be bound to "bar" in foo-mode too, and vice versa.

Thus the only effect of (defvar) over (setq) it that documents the intention of using a symbol as global variable, so telling others to not modify this variable unless manipulation of the behavior of foo-mode is intended. You can attach documentation to the variable, and mark as being defined in your buffer (C-h v foo-state will provide a link to jump to the definition).

Since Emacs Lisp lacks namespaces and is – by default – dynamically scoped, documentation is fundamentally important to avoid conflicts between modules. If I wrote a bar-mode using your foo-mode I might accidentally bind to foo-state, call foo-change-state and then see my mode misbehaving because a variable was unintentionally overwritten. Declaring foo-state doesn't make this impossible, but it at least allows me to catch the error, because C-h v foo-state will reveal that this variable is used by another mode, so I'd better not use it unless I really intend to manipulate that mode.

As a last word: In all of the aforementioned text “mode” can be replaced with Emacs Lisp files. modes are nothing special with regards to symbols. All of the above also holds for Emacs Lisp that do not declare modes, but just contain a bunch of functions.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!