当"父"缓冲区有一个我绑定的同名局部变量时,为什么with-temp-buffer中的代码会抱怨void变量?

aur*_*amo 7 lisp emacs elisp dynamic

我花了很多时间搞清楚我的代码出了什么问题.它在ert单元测试中运行得很好,但是当我在更大的环境中运行它时失败了.以下是一个有效的代码示例:

(defun func (my-var)
  (with-temp-buffer
    (message my-var)))

(func "z")
Run Code Online (Sandbox Code Playgroud)

这按预期打印z.现在我正在编写一个主模式,它有一些缓冲区局部变量.其中一个是my-var.此代码演示了我的问题:

(make-local-variable 'my-var)
(setq my-var "y")

(defun func (my-var)
  (with-temp-buffer
    (message my-var)))

(func "z")
Run Code Online (Sandbox Code Playgroud)

输出?没有,只有这个错误消息:

eval-buffer: Symbol's value as variable is void: my-var
Run Code Online (Sandbox Code Playgroud)

在这个例子中,很容易看到缓冲区局部变量以某种方式干扰动态绑定的my-var.虽然我有多个屏幕值的代码并不是那么容易:-)

所以我的问题是这里真的发生了什么?很明显,temp-buffer以某种方式从"父"缓冲区继承了一个变量,但为什么它有一个void值呢?我会理解它是否会以某种方式获得值"y",但这种行为对我来说就像一个错误.

PS.我正在运行最新的Aquamacs

Tre*_*son 3

有几件事。

首先,您的代码不能按原样运行。您应该在新的 Emacs 调用中尝试此操作。完成后,您会发现需要传递make-local-variable一个符号,如下所示:

(make-local-variable 'my-var)
Run Code Online (Sandbox Code Playgroud)

注意```。

其次,您定义了一个缓冲区局部变量,使其与 的参数同名func,因此任何答案都需要区分两者。

所以,这是我的示例的清理版本:

(make-local-variable 'my-var)
(setq my-var "y")

(defun func (my-param)
  (with-temp-buffer
(message my-param)))

(func "z")
Run Code Online (Sandbox Code Playgroud)

这效果很好。

这让我相信您看到的错误是由于调用 tomake-local-variable前面没有引号引起的my-var

下面提供了原始答案,但它没有解决问题:


查看 的文档make-local-variable。文档字符串是:

make-local-variable 是“C 源代码”中的交互式内置函数。

(make-local-variable 变量)

使 VARIABLE 在当前缓冲区中具有单独的值。其他缓冲区将继续共享共同的默认值。(VARIABLE 的缓冲区本地值开始时与 VARIABLE 之前的值相同。如果 VARIABLE 为空,则它仍然为空。)返回 VARIABLE。

对你来说关键部分是最后一句话。 If the variable was void, it remains void.

这意味着,如果它尚未在全局范围内定义,那么它仍然没有在全局范围内定义。换句话说,它仅在已显式设置的缓冲区中具有绑定。

如果您希望它具有全局值,请setq-default像这样使用:

(setq-default my-var "some-default-value")
Run Code Online (Sandbox Code Playgroud)