Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How do I remove "reference to free variable" warnings on buffer-local variables?

1,060 views
Skip to first unread message

rocky

unread,
Nov 9, 2009, 10:10:31 AM11/9/09
to
I have code that uses buffer local variables. I don't want to declare
this variable global. So how can I remove messages of the form
"reference to free variable `...' " when I byte compile a file?

Thanks.

Tassilo Horn

unread,
Nov 9, 2009, 11:45:14 AM11/9/09
to help-gn...@gnu.org
rocky <ro...@gnu.org> writes:

This warning indicates, that this variable isn't defvar-ed somewhere in
the code you are compiling. But you can supress those like it's stated
in the manual:

,----[ (info "(elisp)Compiler Errors") ]
| You can tell the compiler that a function is defined using
| `declare-function' (*note Declaring Functions::). Likewise, you can
| tell the compiler that a variable is defined using `defvar' with no
| initial value.
|
| You can suppress the compiler warning for a specific use of an
| undefined variable VARIABLE by conditionalizing its use on a `boundp'
| test, like this:
|
| (if (boundp 'VARIABLE) ...VARIABLE...)
`----

So in your case you could add something like

(or (boundp 'some-variable) (defvar some-variable))

at the top of your file.

HTH,
Tassilo

rocky

unread,
Nov 9, 2009, 12:28:33 PM11/9/09
to

And since this is just a compile error, I suppose I can wrap this in
an (eval-when-compile).

>
> at the top of your file.
>
> HTH,
> Tassilo

But doesn't that define the variable globally? And that's not what I
want to do.

In some respects the warning is correct - I am accessing a free
variable. But I want to access a free variable, which I also want to
ensure is only buffer local. I suppose I just want to tell the
compiler that I expect this free variable to be there so don't give me
warnings about it.

Pascal J. Bourguignon

unread,
Nov 9, 2009, 12:40:42 PM11/9/09
to
rocky <ro...@gnu.org> writes:

A free variable is a variable that is used inside a function that is
not defined locally. It must be considered a global variable.

As indicated in the other answers, if no such global variable is
declared, then you get this warning.

The point is that most often, you don't want a global variable
(otherwise you would have used defvar to define it), but you want a
local variable, and you used setq or setf instead of let.

Use let (or let*) to define local variables. Instead of writing:

(defun equa2 (a b c)
(setq delta (- (* b b) (* 4 a c)))
(cond ((< delta 0) '())
((= delta 0) (list (/ (- b) 2 a)))
(t (list (/ (+ (- b) (sqrt delta)) 2 a)
(/ (- (- b) (sqrt delta)) 2 a)))))

write:

(defun equa2 (a b c)
(let ((delta (- (* b b) (* 4 a c))))
(cond ((< delta 0) '())
((= delta 0) (list (/ (- b) 2 a)))
(t (list (/ (+ (- b) (sqrt delta)) 2 a)
(/ (- (- b) (sqrt delta)) 2 a))))))


In general, try to avoid setq or setf, and rather use the functional
programming style.


--
__Pascal Bourguignon__

Drew Adams

unread,
Nov 9, 2009, 12:40:12 PM11/9/09
to Tassilo Horn, help-gn...@gnu.org
> ,----[ (info "(elisp)Compiler Errors") ]
> | You can tell the compiler that a function is defined using
> | `declare-function' (*note Declaring Functions::). Likewise, you can
> | tell the compiler that a variable is defined using `defvar' with no
> | initial value.
> |
> | You can suppress the compiler warning for a specific use of an
> | undefined variable VARIABLE by conditionalizing its use on
> | a `boundp' test, like this:
> |
> | (if (boundp 'VARIABLE) ...VARIABLE...)
> `----
>
> So in your case you could add something like
> (or (boundp 'some-variable) (defvar some-variable))
> at the top of your file.

I don't think so - but I'm no expert on this.

`(defvar some-variable)' does not assign a value to the variable. It is used
(AFAIK) only to suppress a compiler warning. As such, there is no need and no
reason to put it behind `(boundp 'some-variable)'.

Since it does not assign a value, there is typically also no need to take
special measures for local values vs default value. Just use `(defvar
some-variable)' at the top level of a file, if you want to suppress the compiler
warning generally for that variable.

What that passage from the manual is saying, I think, is that you can use
`boundp' to suppress the warning only locally if you want, "for a specific use
of an undefined variable". In the example you gave, `defvar' doesn't really
constitute a "use" of the variable - or if it does, it is not a use that would
cause a warning.

An example of using `boundp' to suppress a warning would be `(if (boundp 'foo)
foo bar)'. Here, if `foo' is not bound, no warning is issued. If `bar' is
unbound, you will get the warning for `bar', since it is not protected by
`boundp'.

IOW, as an alternative to using `(defvar foo)', which suppresses all warnings
about foo being unbound, you can use `(boundp 'foo)' to suppress the unbound
warning for only a specific use of the variable. This warning suppression via
`boundp' was new with Emacs 22.

Again, I'm no expert on this. Others will no doubt correct me. But I'm pretty
sure that the example you gave is not useful: the `boundp' test is not needed,
and it doesn't do anything, since the "use" of the variable for which the
warning would be suppressed here is simply `(defvar some-variable)', which
doesn't issue a warning anyway.

Tassilo Horn

unread,
Nov 9, 2009, 1:58:52 PM11/9/09
to Drew Adams, help-gn...@gnu.org
"Drew Adams" <drew....@oracle.com> writes:

Hi Drew,

> Again, I'm no expert on this. Others will no doubt correct me. But I'm
> pretty sure that the example you gave is not useful: the `boundp' test
> is not needed, and it doesn't do anything, since the "use" of the
> variable for which the warning would be suppressed here is simply
> `(defvar some-variable)', which doesn't issue a warning anyway.

Yes, you are right. And even if it was bound an additional defvar (even
with an init value) would do no harm. So simply put a

(defvar foo)

to suppress the compiler warnings after double-checking that the
warnings are only caused by the fact that the variable is undefined only
at compile time and not at runtime.

Bye,
Tassilo


Stefan Monnier

unread,
Nov 11, 2009, 12:09:33 AM11/11/09
to
> I have code that uses buffer local variables. I don't want to declare
> this variable global. So how can I remove messages of the form
> "reference to free variable `...' " when I byte compile a file?

There is a special use of defvar designed specifically for that
situation:

(defvar <my-var-here>)

this will have no effect other than silence the byte-compiler.


Stefan


PS: If you really really want to, you can put it inside
`eval-when-compile', in which case it may currently work by accident,
but it logically shouldn't work (and may not work in the future) since
(defvar <foo>) does nothing when evaluated, and `eval-when-compile' asks
the byte-compiler to eval its argument instead of byte-compiling it.

0 new messages