diff options
| author | Craig Jennings <c@cjennings.net> | 2024-04-07 13:41:34 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2024-04-07 13:41:34 -0500 |
| commit | 754bbf7a25a8dda49b5d08ef0d0443bbf5af0e36 (patch) | |
| tree | f1190704f78f04a2b0b4c977d20fe96a828377f1 /devdocs/elisp/local-variables.html | |
new repository
Diffstat (limited to 'devdocs/elisp/local-variables.html')
| -rw-r--r-- | devdocs/elisp/local-variables.html | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/devdocs/elisp/local-variables.html b/devdocs/elisp/local-variables.html new file mode 100644 index 00000000..e1e6852d --- /dev/null +++ b/devdocs/elisp/local-variables.html @@ -0,0 +1,66 @@ + <h3 class="section">Local Variables</h3> <p>Global variables have values that last until explicitly superseded with new values. Sometimes it is useful to give a variable a <em>local value</em>—a value that takes effect only within a certain part of a Lisp program. When a variable has a local value, we say that it is <em>locally bound</em> to that value, and that it is a <em>local variable</em>. </p> <p>For example, when a function is called, its argument variables receive local values, which are the actual arguments supplied to the function call; these local bindings take effect within the body of the function. To take another example, the <code>let</code> special form explicitly establishes local bindings for specific variables, which take effect only within the body of the <code>let</code> form. </p> <p>We also speak of the <em>global binding</em>, which is where (conceptually) the global value is kept. </p> <p>Establishing a local binding saves away the variable’s previous value (or lack of one). We say that the previous value is <em>shadowed</em>. Both global and local values may be shadowed. If a local binding is in effect, using <code>setq</code> on the local variable stores the specified value in the local binding. When that local binding is no longer in effect, the previously shadowed value (or lack of one) comes back. </p> <p>A variable can have more than one local binding at a time (e.g., if there are nested <code>let</code> forms that bind the variable). The <em>current binding</em> is the local binding that is actually in effect. It determines the value returned by evaluating the variable symbol, and it is the binding acted on by <code>setq</code>. </p> <p>For most purposes, you can think of the current binding as the innermost local binding, or the global binding if there is no local binding. To be more precise, a rule called the <em>scoping rule</em> determines where in a program a local binding takes effect. The default scoping rule in Emacs Lisp is called <em>dynamic scoping</em>, which simply states that the current binding at any given point in the execution of a program is the most recently-created binding for that variable that still exists. For details about dynamic scoping, and an alternative scoping rule called <em>lexical scoping</em>, see <a href="variable-scoping">Variable Scoping</a>. </p> <p>The special forms <code>let</code> and <code>let*</code> exist to create local bindings: </p> <dl> <dt id="let">Special Form: <strong>let</strong> <em>(bindings…) forms…</em> +</dt> <dd> +<p>This special form sets up local bindings for a certain set of variables, as specified by <var>bindings</var>, and then evaluates all of the <var>forms</var> in textual order. Its return value is the value of the last form in <var>forms</var>. The local bindings set up by <code>let</code> will be in effect only within the body of <var>forms</var>. </p> <p>Each of the <var>bindings</var> is either (i) a symbol, in which case that symbol is locally bound to <code>nil</code>; or (ii) a list of the form <code>(<var>symbol</var> <var>value-form</var>)</code>, in which case <var>symbol</var> is locally bound to the result of evaluating <var>value-form</var>. If <var>value-form</var> is omitted, <code>nil</code> is used. </p> <p>All of the <var>value-form</var>s in <var>bindings</var> are evaluated in the order they appear and <em>before</em> binding any of the symbols to them. Here is an example of this: <code>z</code> is bound to the old value of <code>y</code>, which is 2, not the new value of <code>y</code>, which is 1. </p> <div class="example"> <pre class="example">(setq y 2) + ⇒ 2 +</pre> + +<pre class="example">(let ((y 1) + (z y)) + (list y z)) + ⇒ (1 2) +</pre> +</div> <p>On the other hand, the order of <em>bindings</em> is unspecified: in the following example, either 1 or 2 might be printed. </p> <div class="example"> <pre class="example">(let ((x 1) + (x 2)) + (print x)) +</pre> +</div> <p>Therefore, avoid binding a variable more than once in a single <code>let</code> form. </p> +</dd> +</dl> <dl> <dt id="let*">Special Form: <strong>let*</strong> <em>(bindings…) forms…</em> +</dt> <dd> +<p>This special form is like <code>let</code>, but it binds each variable right after computing its local value, before computing the local value for the next variable. Therefore, an expression in <var>bindings</var> can refer to the preceding symbols bound in this <code>let*</code> form. Compare the following example with the example above for <code>let</code>. </p> <div class="example"> <pre class="example">(setq y 2) + ⇒ 2 +</pre> + +<pre class="example">(let* ((y 1) + (z y)) ; <span class="roman">Use the just-established value of <code>y</code>.</span> + (list y z)) + ⇒ (1 1) +</pre> +</div> </dd> +</dl> <dl> <dt id="letrec">Special Form: <strong>letrec</strong> <em>(bindings…) forms…</em> +</dt> <dd> +<p>This special form is like <code>let*</code>, but all the variables are bound before any of the local values are computed. The values are then assigned to the locally bound variables. This is only useful when lexical binding is in effect, and you want to create closures that refer to bindings that would otherwise not yet be in effect when using <code>let*</code>. </p> <p>For instance, here’s a closure that removes itself from a hook after being run once: </p> <div class="lisp"> <pre class="lisp">(letrec ((hookfun (lambda () + (message "Run once") + (remove-hook 'post-command-hook hookfun)))) + (add-hook 'post-command-hook hookfun)) +</pre> +</div> </dd> +</dl> <dl> <dt id="dlet">Special Form: <strong>dlet</strong> <em>(bindings…) forms…</em> +</dt> <dd> +<p>This special form is like <code>let</code>, but it binds all variables dynamically. This is rarely useful—you usually want to bind normal variables lexically, and special variables (i.e., variables that are defined with <code>defvar</code>) dynamically, and this is what <code>let</code> does. </p> <p><code>dlet</code> can be useful when interfacing with old code that assumes that certain variables are dynamically bound (see <a href="dynamic-binding">Dynamic Binding</a>), but it’s impractical to <code>defvar</code> these variables. <code>dlet</code> will temporarily make the bound variables special, execute the forms, and then make the variables non-special again. </p> +</dd> +</dl> <dl> <dt id="named-let">Special Form: <strong>named-let</strong> <em>name bindings &rest body</em> +</dt> <dd> +<p>This special form is a looping construct inspired from the Scheme language. It is similar to <code>let</code>: It binds the variables in <var>bindings</var>, and then evaluates <var>body</var>. However, <code>named-let</code> also binds <var>name</var> to a local function whose formal arguments are the variables in <var>bindings</var> and whose body is <var>body</var>. This allows <var>body</var> to call itself recursively by calling <var>name</var>, where the arguments passed to <var>name</var> are used as the new values of the bound variables in the recursive invocation. </p> <p>Example of a loop summing a list of numbers: </p> <div class="lisp"> <pre class="lisp">(named-let sum ((numbers '(1 2 3 4)) + (running-sum 0)) + (if numbers + (sum (cdr numbers) (+ running-sum (car numbers))) + running-sum)) +⇒ 10 +</pre> +</div> <p>Recursive calls to <var>name</var> that occur in <em>tail positions</em> in <var>body</var> are guaranteed to be optimized as <em>tail calls</em>, which means that they will not consume any additional stack space no matter how deeply the recursion runs. Such recursive calls will effectively jump to the top of the loop with new values for the variables. </p> <p>A function call is in the tail position if it’s the very last thing done so that the value returned by the call is the value of <var>body</var> itself, as is the case in the recursive call to <code>sum</code> above. </p> +</dd> +</dl> <p>Here is a complete list of the other facilities that create local bindings: </p> <ul> <li> Function calls (see <a href="functions">Functions</a>). </li> +<li> Macro calls (see <a href="macros">Macros</a>). </li> +<li> <code>condition-case</code> (see <a href="errors">Errors</a>). </li> +</ul> <p>Variables can also have buffer-local bindings (see <a href="buffer_002dlocal-variables">Buffer-Local Variables</a>); a few variables have terminal-local bindings (see <a href="multiple-terminals">Multiple Terminals</a>). These kinds of bindings work somewhat like ordinary local bindings, but they are localized depending on where you are in Emacs. </p> <dl> <dt id="max-specpdl-size">User Option: <strong>max-specpdl-size</strong> +</dt> <dd> + <p>This variable defines the limit on the total number of local variable bindings and <code>unwind-protect</code> cleanups (see <a href="cleanups">Cleaning Up from Nonlocal Exits</a>) that are allowed before Emacs signals an error (with data <code>"Variable binding depth exceeds +max-specpdl-size"</code>). </p> <p>This limit, with the associated error when it is exceeded, is one way that Lisp avoids infinite recursion on an ill-defined function. <code>max-lisp-eval-depth</code> provides another limit on depth of nesting. See <a href="eval#Definition-of-max_002dlisp_002deval_002ddepth">Eval</a>. </p> <p>The default value is 1600. Entry to the Lisp debugger increases the value, if there is little room left, to make sure the debugger itself has room to execute. </p> +</dd> +</dl><div class="_attribution"> + <p class="_attribution-p"> + Copyright © 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/Local-Variables.html" class="_attribution-link">https://www.gnu.org/software/emacs/manual/html_node/elisp/Local-Variables.html</a> + </p> +</div> |
