summaryrefslogtreecommitdiff
path: root/devdocs/elisp/converting-to-lexical-binding.html
blob: 00cf852f7b3a66d21b3da819cc28b5ee6297fbdc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 <h4 class="subsection">Converting to Lexical Binding</h4> <p>Converting an Emacs Lisp program to lexical binding is easy. First, add a file-local variable setting of <code>lexical-binding</code> to <code>t</code> in the header line of the Emacs Lisp source file (see <a href="file-local-variables">File Local Variables</a>). 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. </p>   <p>A simple way to find out which variables need a variable definition is to byte-compile the source file. See <a href="byte-compilation">Byte Compilation</a>. If a non-special variable is used outside of a <code>let</code> 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 <code>let</code> 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. </p> <p>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 <code>defvar</code> before the first use of that variable. </p> <p>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 add a <code>defvar</code> 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 be used.) </p> <h4 class="subsubheading">Cross-file variable checking</h4> <p><strong>Caution:</strong> This is an experimental feature that may change or disappear without prior notice. </p> <p>The byte-compiler can also warn about lexical variables that are special in other Emacs Lisp files, often indicating a missing <code>defvar</code> declaration. This useful but somewhat specialized check requires three steps: </p> <ol> <li> Byte-compile all files whose special variable declarations may be of interest, with the environment variable <code>EMACS_GENERATE_DYNVARS</code> set 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 <samp>.dynvars</samp> for each compiled Emacs Lisp file. </li>
<li> Concatenate the <samp>.dynvars</samp> files into a single file. </li>
<li> Byte-compile the files that need to be checked, this time with the environment variable <code>EMACS_DYNVARS_FILE</code> set to the name of the aggregated file created in step 2. </li>
</ol> <p>Here is an example illustrating how this could be done, assuming that a Unix shell and <code>make</code> are used for byte-compilation: </p> <div class="example"> <pre class="example">$ rm *.elc                                # force recompilation
$ EMACS_GENERATE_DYNVARS=1 make           # generate .dynvars
$ cat *.dynvars &gt; ~/my-dynvars            # combine .dynvars
$ rm *.elc                                # force recompilation
$ EMACS_DYNVARS_FILE=~/my-dynvars make    # perform checks
</pre>
</div><div class="_attribution">
  <p class="_attribution-p">
    Copyright &copy; 1990-1996, 1998-2022 Free Software Foundation, Inc. <br>Licensed under the GNU GPL license.<br>
    <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Converting-to-Lexical-Binding.html" class="_attribution-link">https://www.gnu.org/software/emacs/manual/html_node/elisp/Converting-to-Lexical-Binding.html</a>
  </p>
</div>