Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does code in with-temp-buffer complain about void variable when "parent" buffer has a local variable of the same name I've bound?

I just spent ages figuring out what was wrong with my code. It worked just fine in ert unit tests, but failed when I ran it in a larger context. Here is an example of a code which worked:

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

(func "z")

This prints z as expected. Now I was writing a major mode which had some buffer-local variables. One of these was my-var. This code demonstrates my issue:

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

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

(func "z")

The output? There is none, only this error message:

eval-buffer: Symbol's value as variable is void: my-var

In this example it is easy to see that the buffer-local variable interferes somehow with the dynamically bound my-var. It wasn't so easy when I had multiple screens worth of code though :-)

So my question is what is really going on here? It's obvious that the temp-buffer somehow inherits a variable from the "parent" buffer, but why does it have a void value? I would understand if it would get the value "y" somehow, but this behavior feels like a bug to me.

PS. I'm running the latest Aquamacs

like image 400
auramo Avatar asked Jan 25 '12 18:01

auramo


1 Answers

A couple of things.

First, your code doesn't work as-is. You should try this in a new invocation of Emacs. Once you do, you'll see that you need to pass make-local-variable a symbol, like so:

(make-local-variable 'my-var)

Note the ```.

Second, you've defined a buffer-local variable to have the same name as the parameter to func, so any answer needs to distinguish between the two.

So, here's my cleaned up version of your example:

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

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

(func "z")

And this works just fine.

Which leads me to believe that the error you're seeing is from the call to make-local-variable without the quote in front of my-var.

Original answer provided below, though it doesn't address the problem:


Check out the documentation for make-local-variable. The doc string is:

make-local-variable is an interactive built-in function in `C source code'.

(make-local-variable VARIABLE)

Make VARIABLE have a separate value in the current buffer. Other buffers will continue to share a common default value. (The buffer-local value of VARIABLE starts out as the same value VARIABLE previously had. If VARIABLE was void, it remains void.) Return VARIABLE.

The key part for you is the last sentence. If the variable was void, it remains void.

This means that if it was not already defined globally, it is still not defined globally. In other words, it only has a binding in the buffers in which it has been explicitly set.

If you want it to have a global value, use setq-default like so:

(setq-default my-var "some-default-value")
like image 87
Trey Jackson Avatar answered Sep 28 '22 20:09

Trey Jackson