diff options
Diffstat (limited to 'devdocs/elisp/deferred-eval.html')
| -rw-r--r-- | devdocs/elisp/deferred-eval.html | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/devdocs/elisp/deferred-eval.html b/devdocs/elisp/deferred-eval.html new file mode 100644 index 00000000..18d7dc2f --- /dev/null +++ b/devdocs/elisp/deferred-eval.html @@ -0,0 +1,55 @@ + <h3 class="section">Deferred and Lazy Evaluation</h3> <p>Sometimes it is useful to delay the evaluation of an expression, for example if you want to avoid performing a time-consuming calculation if it turns out that the result is not needed in the future of the program. The <samp>thunk</samp> library provides the following functions and macros to support such <em>deferred evaluation</em>: </p> <dl> <dt id="thunk-delay">Macro: <strong>thunk-delay</strong> <em>forms…</em> +</dt> <dd><p>Return a <em>thunk</em> for evaluating the <var>forms</var>. A thunk is a closure (see <a href="closures">Closures</a>) that inherits the lexical environment of the <code>thunk-delay</code> call. Using this macro requires <code>lexical-binding</code>. </p></dd> +</dl> <dl> <dt id="thunk-force">Function: <strong>thunk-force</strong> <em>thunk</em> +</dt> <dd><p>Force <var>thunk</var> to perform the evaluation of the forms specified in the <code>thunk-delay</code> that created the thunk. The result of the evaluation of the last form is returned. The <var>thunk</var> also “remembers” that it has been forced: Any further calls of <code>thunk-force</code> with the same <var>thunk</var> will just return the same result without evaluating the forms again. </p></dd> +</dl> <dl> <dt id="thunk-let">Macro: <strong>thunk-let</strong> <em>(bindings…) forms…</em> +</dt> <dd><p>This macro is analogous to <code>let</code> but creates “lazy” variable bindings. Any binding has the form <code>(<var>symbol</var> <var><span class="nolinebreak">value-form</span></var>)</code>. Unlike <code>let</code>, the evaluation of any <var>value-form</var> is deferred until the binding of the according <var>symbol</var> is used for the first time when evaluating the <var>forms</var>. Any <var>value-form</var> is evaluated at most once. Using this macro requires <code>lexical-binding</code>. </p></dd> +</dl> <p>Example: </p> <div class="example"> <pre class="example">(defun f (number) + (thunk-let ((derived-number + (progn (message "Calculating 1 plus 2 times %d" number) + (1+ (* 2 number))))) + (if (> number 10) + derived-number + number))) +</pre> + +<pre class="example">(f 5) +⇒ 5 +</pre> + +<pre class="example">(f 12) +-| Calculating 1 plus 2 times 12 +⇒ 25 +</pre> + +</div> <p>Because of the special nature of lazily bound variables, it is an error to set them (e.g. with <code>setq</code>). </p> <dl> <dt id="thunk-let*">Macro: <strong>thunk-let*</strong> <em>(bindings…) forms…</em> +</dt> <dd><p>This is like <code>thunk-let</code> but any expression in <var>bindings</var> is allowed to refer to preceding bindings in this <code>thunk-let*</code> form. Using this macro requires <code>lexical-binding</code>. </p></dd> +</dl> <div class="example"> <pre class="example">(thunk-let* ((x (prog2 (message "Calculating x...") + (+ 1 1) + (message "Finished calculating x"))) + (y (prog2 (message "Calculating y...") + (+ x 1) + (message "Finished calculating y"))) + (z (prog2 (message "Calculating z...") + (+ y 1) + (message "Finished calculating z"))) + (a (prog2 (message "Calculating a...") + (+ z 1) + (message "Finished calculating a")))) + (* z x)) + +-| Calculating z... +-| Calculating y... +-| Calculating x... +-| Finished calculating x +-| Finished calculating y +-| Finished calculating z +⇒ 8 + +</pre> +</div> <p><code>thunk-let</code> and <code>thunk-let*</code> use thunks implicitly: their expansion creates helper symbols and binds them to thunks wrapping the binding expressions. All references to the original variables in the body <var>forms</var> are then replaced by an expression that calls <code>thunk-force</code> with the according helper variable as the argument. So, any code using <code>thunk-let</code> or <code>thunk-let*</code> could be rewritten to use thunks, but in many cases using these macros results in nicer code than using thunks explicitly. </p><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/Deferred-Eval.html" class="_attribution-link">https://www.gnu.org/software/emacs/manual/html_node/elisp/Deferred-Eval.html</a> + </p> +</div> |
