Converting an Emacs Lisp program to lexical binding is easy. First,
add a file-local variable setting of
t in the header line of the Emacs Lisp source file (see File Local Variables). Second, check that every variable in the program
which needs to be dynamically bound has a variable definition, so that
it is not inadvertently bound lexically.
A simple way to find out which variables need a variable definition
is to byte-compile the source file. See Byte Compilation. 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 will also issue a warning if you use a
special variable as a function argument.
A warning about a reference or an assignment to a free variable is
usually a clear sign that that variable should be marked as
dynamically scoped, so you need to add an appropriate
before the first use of that variable.
A warning about an unused variable may be a good hint that the
variable was intended to be dynamically scoped (because it is actually
used, but in another function), but it may also be an indication that
the variable is simply really not used and could simply be removed.
So you need to find out which case it is, and based on that, either
defvar or remove the variable altogether. If removal is
not possible or not desirable (typically because it is a formal
argument and that we cannot or don’t want to change all the callers),
you can also add a leading underscore to the variable’s name to
indicate to the compiler that this is a variable known not to
Caution: This is an experimental feature that may change or disappear without prior notice.
The byte-compiler can also warn about lexical variables that are
special in other Emacs Lisp files, often indicating a missing
defvar declaration. This useful but somewhat specialized check
requires three steps:
EMACS_GENERATE_DYNVARSset to a nonempty string. These are typically all the files in the same package or related packages or Emacs subsystems. The process will generate a file whose name ends in .dynvars for each compiled Emacs Lisp file.
EMACS_DYNVARS_FILEset to the name of the aggregated file created in step 2.
Here is an example illustrating how this could be done, assuming that
a Unix shell and
make are used for byte-compilation:
$ rm *.elc # force recompilation $ EMACS_GENERATE_DYNVARS=1 make # generate .dynvars $ cat *.dynvars > ~/my-dynvars # combine .dynvars $ rm *.elc # force recompilation $ EMACS_DYNVARS_FILE=~/my-dynvars make # perform checks