[Home]

Free Variable

This is a variable without a defvar. Setting it may cause problems for other people. Example:

This will return “test” as expected, and still cause a warning, because of the typo (names vs. name). The problem only appears if other people call foo, because DynamicBinding will clobber their variable:

This will now return “test” instead of “good” – because foo clobbered the names variable.

Sometimes such warnings cannot be avoided. Example:

This will work for XEmacs, never run on Emacs, and when compiled you will get a warning on Emacs… Ignore it.

You can get rid of byte-compiler warnings about free variables if you know that they are not real problems by letting the compiler know about them.

Will make the byte-compiler not warn about my-free-variable being free. Note, this does not actually introduce a binding for my-free-variable .

(see also ElispCompilerWarnings )

CategoryCode ComparativeEmacsology

Next: Functions , Previous: Control Structures , Up: Emacs Lisp   [ Contents ][ Index ]

12 Variables

A variable is a name used in a program to stand for a value. In Lisp, each variable is represented by a Lisp symbol (see Symbols ). The variable name is simply the symbol’s name, and the variable’s value is stored in the symbol’s value cell 9 . See Symbol Components . In Emacs Lisp, the use of a symbol as a variable is independent of its use as a function name.

As previously noted in this manual, a Lisp program is represented primarily by Lisp objects, and only secondarily as text. The textual form of a Lisp program is given by the read syntax of the Lisp objects that constitute the program. Hence, the textual form of a variable in a Lisp program is written using the read syntax for the symbol representing the variable.

  • Global Variables
  • Variables that Never Change
  • Local Variables
  • When a Variable is Void
  • Defining Global Variables
  • Tips for Defining Variables Robustly
  • Accessing Variable Values
  • Setting Variable Values
  • Running a function when a variable is changed.
  • Scoping Rules for Variable Bindings
  • Buffer-Local Variables
  • File Local Variables
  • Directory Local Variables
  • Connection Local Variables
  • Variable Aliases
  • Variables with Restricted Values
  • Generalized Variables
  • Multisession Variables

To be precise, under the default dynamic scoping rule, the value cell always holds the variable’s current value, but this is not the case under the lexical scoping rule. See Scoping Rules for Variable Bindings , for details.

10.1 Introduction to Evaluation

The Lisp interpreter, or evaluator, is the part of Emacs that computes the value of an expression that is given to it. When a function written in Lisp is called, the evaluator computes the value of the function by evaluating the expressions in the function body. Thus, running any Lisp program really means running the Lisp interpreter.

A Lisp object that is intended for evaluation is called a form or expression 1 . The fact that forms are data objects and not merely text is one of the fundamental differences between Lisp-like languages and typical programming languages. Any object can be evaluated, but in practice only numbers, symbols, lists and strings are evaluated very often.

In subsequent sections, we will describe the details of what evaluation means for each kind of form.

It is very common to read a Lisp form and then evaluate the form, but reading and evaluation are separate activities, and either can be performed alone. Reading per se does not evaluate anything; it converts the printed representation of a Lisp object to the object itself. It is up to the caller of read to specify whether this object is a form to be evaluated, or serves some entirely different purpose. See Input Functions .

Evaluation is a recursive process, and evaluating a form often involves evaluating parts within that form. For instance, when you evaluate a function call form such as (car x) , Emacs first evaluates the argument (the subform x ). After evaluating the argument, Emacs executes the function ( car ), and if the function is written in Lisp, execution works by evaluating the body of the function (in this example, however, car is not a Lisp function; it is a primitive function implemented in C). See Functions , for more information about functions and function calls.

Evaluation takes place in a context called the environment , which consists of the current values and bindings of all Lisp variables (see Variables ). 2 Whenever a form refers to a variable without creating a new binding for it, the variable evaluates to the value given by the current environment. Evaluating a form may also temporarily alter the environment by binding variables (see Local Variables ).

Evaluating a form may also make changes that persist; these changes are called side effects . An example of a form that produces a side effect is (setq foo 1) .

Do not confuse evaluation with command key interpretation. The editor command loop translates keyboard input into a command (an interactively callable function) using the active keymaps, and then uses call-interactively to execute that command. Executing the command usually involves evaluation, if the command is written in Lisp; however, this step is not considered a part of command key interpretation. See Command Loop .

  • It is sometimes also referred to as an S-expression or sexp , but we generally do not use this terminology in this manual. ↩
  • This definition of “environment" is specifically not intended to include all the data that can affect the result of a program. ↩

为啥一个无关的局部绑定会引起编译警告?

The compiler will issue a warning message

Warning: assignment to free variable -/var

if you evaluate the following forms :

remove the local binding of _ , then evaluate the following forms :

byte-compile-file the entire file stead of using byte-compile :

Everything goes well.

Why would this happen? I see no difference among the above snippets.

emacs-version: 29.1 system-configuration: x86_64-w64-mingw32

从 Stack Exchange 上搬来的:

卧槽,藏这么深都能找到。收藏了,明天细看

我看了手册上关于 defvar without VALUE 的示例. 似乎是

为啥到我那个例子里就会报 warning?

草,这个问题没我想的那么简单,我对 defvar 的理解还不够。

找到一个类似的贴子: let修改临时变量能否和autoload搭配使用 - Emacs-Lisp - Emacs China (emacs-china.org)

你没看到 dlet 用了两层 let 么,你这少用了一层。

题目的代码属于典型的货物崇拜,连代码是干啥的都不清楚就写上去,还“看不出有什么区别”

defvar 就不该用在 quasiquote 里,不在 toplevel 编译器根本看不到,当然会报警告

没看懂你想指责什么. 你想说我不明白这个代码的含义所以不该把它写下来, 不该问问题吗?

说这话你不觉得很??? 就是没看出来才问问题的好吗

另外你在 stack exchange 上的代码复现不出来

Ldbeth 用的应该不是 29 正式版,我猜

我大概知道原因了,不过得整理一下

* Lisp Changes in Emacs 29.1 ** Interpreted closures are “safe for space”. As was already the case for byte-compiled closures, instead of capturing the whole current lexical environment, interpreted closures now only capture the part of the environment that they need. The previous behavior could occasionally lead to memory leaks or to problems where a printed closure would not be 'read’able because of an un’read’able value in an unrelated lexical variable.

如果没问题的话应该就是这个,但是细节还要点时间分析

上面,我们使用的都是 Emacs 29.1,在 Emacs 28.2 上,你给出的两段代码都是可以正常运行的。想来想去只能是 Emacs 29.1 引入的一个东西导致的: gnu.org/software/emacs/news/NEWS.29.1

在 Emacs 28.2 中,位于 (let (_) 中的 (defvar sym) 的 sym 会和 _ 一起添加到词法环境中,下面的例子可以说明这一点:

而在 Emacs 29 中,我们得到的是如下结果:

我简单对比了一下 28 和 29 的 function 实现,发现 29 多了以下内容:

在 28 中没有 if,只有 Fcons 分支部分的代码。这个多出来的 Vinternal_make_interpreted_closure_function 应该做一些清理工作,去掉无用的词法环境变量。它绑定的函数位于 cconv.el 中,为 cconv-make-interpreted-closure 。它主要有这几个特点: (下面使用 trace-function 'cconv-make-interpreted-closure) 观察其行为:

  • 如果词法环境排除动态变量后为空,那么不进行修改

这也对应 (let ()... 的情况:

  • 如果环境中存在词法绑定则继续,具体过程大概是寻找函数中 所需 的词法变量和动态变量,然后重新组合得到环境,寻找所需词法和动态变量的过程是通过调用 cconv-fv 完成的:

比较有意思的是它返回的动态变量列表似乎 总为空 ,它的返回值结构为 (LEX_LIST . DYN_LIST) ,例如如下调用:

你可以在 Emacs 29 中多试几个例子。

动态变量列表总为空就导致生成闭包的 env 中没有动态变量,从而导致 byte-compile 时出现 warning

看上去很吓人是吧,不过整个 Emacs 29 既然都能正常使用那就说明这是没问题的。维护者能知道能这样做就行。老实说 LZ 的样例代码不是什么常规用法,还是像 LdBeth 所说遵守约定正常使用就行,不用在边缘情况下耍。虽然会报 Warning 但是生成的字节码是没有问题的,可以 disassemble 对比一下。

是的,你因为不知道代码作用胡乱写出来的不遵守代码规范东西触发了编程语言实现者完全没有预料到的边界条件,只能通过分析具体实现才能解释这个现象,这样的问题对“正常写代码”的别人来说没有实际帮助。

就是没看出来才问问题的好吗

defvar 和 let 的组合用法官方文档都有,显然你没认真查过。

至于复现问题,我手上没有电脑,手机上只有 28.2。

题目里面 defvar 是在 let 外面的,你这在里面,效果不一定一样。

是这样的, 但不妨碍问题被问出来, 只是你不喜欢而已.

我看过了, 不然为什么要这么回复 include-yy

我这里(macOS 10.13, Emacs 26.3 & 27.2 & 28.3 & 29.1)无法复现。

你应该给出测试环境、完整代码和测试步骤,你没有交代的部分有可能是关键信息。

那也是,不过原理就是我上面贴子解释的那样了

偷懒了, 版本信息我写在原帖上面, 这边 没搬运过来. 下次注意

问问题当然没关系,但是你这个代码来自另外一个主题,而且是一个功能上完全不必要的写法,为了不误导别人我建议你把原来的主题里代码修改了,如果你不知道怎么修改,我回去可以给你写如何修改的指导。

你发在 stackexchange 的帖子也没有交代清楚,这就是为什么评论那位也不能复现。

已改. 你要说把代码写得规范一点, 那当然合情合理. 但是遇到这种两种写法前后行为不一致的情形, 还是会纠结一下. 其实我本地的代码早上就改了, 因为这个报 warning 看着也麻烦, 但忍不住还是会过来再问一下.

IMAGES

  1. emacs lisp for beginner

    emacs lisp assignment to free variable

  2. Binding Emacs Lisp variables with lispy

    emacs lisp assignment to free variable

  3. How can I start learning Emacs Lisp?

    emacs lisp assignment to free variable

  4. Emacs-Lisp Basics

    emacs lisp assignment to free variable

  5. Emacs Lisp. Overview

    emacs lisp assignment to free variable

  6. Emacs Lisp Tutorial by Example

    emacs lisp assignment to free variable

VIDEO

  1. EmacsLispのある生活 [1/4]

  2. Learning Elisp 3

  3. Little bits of Lisp

  4. How to manipulate property lists in Emacs Lisp? plist-member, plist-get

  5. write grep in emacs lisp

  6. Algebra: 3x3 with free variable

COMMENTS

  1. suppress warning: assignment to free variable (and others)

    In order to disable this (or other) warning, you'll need to set the value of byte-compile-warnings. You can do this as a file-local variable by adding the following snippet to the end of the file. ;; Local Variables: ;; byte-compile-warnings: (not free-vars) ;; End: You can also set this globally. You can replace (not free-vars) with (not free ...

  2. emacs

    8. When you are compiling the file where you reference the variable emacs-root, the variable must be already defined. The easiest way to avoid the warning is to add. in el-get-settings.el before the offending form. Alternatively, you can move the defvar from init.el to el-get-settings.el.

  3. Fixing "reference/assignment to free variable" warning during

    Warning: reference to free variable 'font-lock-beg' Warning: assignment to free variable 'font-lock-beg' Documentation says: font-lock-extend-region-functions is a variable defined in 'font-lock.el'. Each function is called with no argument; it is expected to adjust the dynamically bound variables 'font-lock-beg' and 'font-lock-end ...

  4. "assignment to free variable" warning after defvar

    Remember that, (defvar foo) and (defvar foo nil) has different meaning and the behavior can be different. On 28.2 the result is also different, although the byte compiler would not generate a complain for the free variable. Whether foo is bound or undeclared would not make a difference to the result. Op mentioned the FIXME comment in dlet.

  5. Setting Variables (GNU Emacs Lisp Reference Manual)

    12.8 Setting Variable Values. The usual way to change the value of a variable is with the special form . When you need to compute the choice of variable at run time, use the function . Special Form: setq [symbol form]… ¶. This special form is the most common method of changing a variable's value. Each symbol is given a new value, which is ...

  6. How to get rid of warning: "assignment to free variable ...

    The use-package documentation covers dealing with warnings in the Byte-compiling your .emacs section. Basically, use the :defines keyword, which tells use-package to add a dummy variable to sate the byte-compiler. There is an equivalent :functions keyword for functions. 4.

  7. Programming in Emacs Lisp

    3.6.4 How let Binds Variables. Emacs Lisp supports two different ways of binding variable names to their values. These ways affect the parts of your program where a particular binding is valid. For historical reasons, Emacs Lisp uses a form of variable binding called dynamic binding by default.

  8. Defining Variables (GNU Emacs Lisp Reference Manual)

    12.5 Defining Global Variables. A variable definition is a construct that announces your intention to use a symbol as a global variable. It uses the special forms defvar or defconst, which are documented below. A variable definition serves three purposes. First, it informs people who read the code that the symbol is intended to be used a ...

  9. Converting to Lexical Binding (GNU Emacs Lisp Reference Manual)

    Converting an Emacs Lisp program to lexical binding is easy. ... If a non-special variable is used outside of a let form, the byte-compiler will warn about reference or assignment to a free variable. If a non-special variable is bound but not used within a let form, the byte-compiler will warn about an unused lexical variable. The byte-compiler ...

  10. GNU Emacs Lisp Reference Manual

    In the text of a Lisp program, variables are written using the syntax for symbols. In Lisp, unlike most programming languages, programs are represented primarily as Lisp objects and only secondarily as text. The Lisp objects used for variables are symbols: the symbol name is the variable name, and the variable's value is stored in the value ...

  11. EmacsWiki: Free Variable

    Ignore it. You can get rid of byte-compiler warnings about free variables if you know that they are not real problems by letting the compiler know about them. (eval-when-compile. (defvar my-free-variable)) Will make the byte-compiler not warn about my-free-variable being free. Note, this does not actually introduce a binding for my-free-variable.

  12. flymake

    7 6 warning e-f-b-c assignment to free variable 'var1' 8 24 warning e-f-b-c reference to free variable 'var2' Why setopt is not underlined here? I know it's a new macro introduced in Emacs 29 but I wonder if it is intended to be like this or the linter is just misbehaving here.

  13. Variables (GNU Emacs Lisp Reference Manual)

    12 Variables. A variable is a name used in a program to stand for a value. In Lisp, each variable is represented by a Lisp symbol (see Symbols).The variable name is simply the symbol's name, and the variable's value is stored in the symbol's value cell 9.See Symbol Components.In Emacs Lisp, the use of a symbol as a variable is independent of its use as a function name.

  14. GNU Emacs Lisp Reference Manual: Variables

    A variable is a name used in a program to stand for a value. Nearly all programming languages have variables of some sort. In the text of a Lisp program, variables are written using the syntax for symbols. In Lisp, unlike most programming languages, programs are represented primarily as Lisp objects and only secondarily as text.

  15. 10.1 Introduction to Evaluation

    The Lisp interpreter, or evaluator, is the part of Emacs that computes the value of an expression that is given to it. When a function written in Lisp is called, the evaluator computes the value of the function by evaluating the expressions in the function body. Thus, running any Lisp program really means running the Lisp interpreter.

  16. Bind multiple values directly from list without ...

    For example, let's say I have a function that returns a list of two lists: (defun test-func () (setq a '(a b)) (setq b '(c d)) `(,a ,b)) If I want to assign the first return value to list-a and the second return value to list-b, I can do this by using a temporary variable temp, for example:

  17. 为啥一个无关的局部绑定会引起编译警告?

    Ldbeth 用的应该不是 29 正式版,我猜. 我大概知道原因了,不过得整理一下. * Lisp Changes in Emacs 29.1. ** Interpreted closures are "safe for space". As was already the case for byte-compiled closures, instead of capturing the whole current lexical environment, interpreted closures now only capture the part of the ...

  18. Emacs lisp refactoring

    When you have side-effect-free code (as cl coding standards encourage but is rarely the case in emacs lisp code) make use of emr-el-extract-to-let to avoid jumping around. Use let* if your variables depend upon one another. This pattern is more common within emacs lisp code than the use of unassigned let expressions (though this is far from ...

  19. emacs

    Note that in Emacs Lisp, symbols have a value cell and a function cell, which are distinct. When you evaluate a symbol, you get its value.When you evaluate a list beginning with that symbol, you call its function.This is why you can have a variable and a function with the same name.