Search code examples
emacselisp

What are the dangers of assigning to a free variable in Emacs Lisp?


Adding (setq foo 1) to the code without defining the variable foo using defvar will result in the following warning generated by Emacs byte-compiler:

assignment to free variable `foo'

What are the dangers associated with assigning to such free variable without prior definition?


Solution

  • Emacs Lisp uses Dynamic Binding by default, so when you write

    (defun my-fun-1 (...)
      ...
      (setq foo 1)
      ...)
    

    and get your warning, the code is equivalent to having (defvar foo) before the defun.

    This means that the my-fun-1 above shares the value of foo with

    (defun maybe-start-ww3 ()
       (when (= 1 foo)
         (launch-missiles)))
    

    this is not always bad; much ELisp legacy code uses such globals to pass state. However, this is a very bad style, if you use the same variable name (e.g., date) for these purposes in two unrelated places, the consequences could be unpredictable.

    In short, if you use the free variable in a single place, there is no reason not to bind it. If you use it to pass state, you should defvar it and use a long name which is not likely to be used by someone else - and you should refactor your code to avoid that.