diff options
Diffstat (limited to 'doc/lispref/eval.texi')
-rw-r--r-- | doc/lispref/eval.texi | 123 |
1 files changed, 118 insertions, 5 deletions
diff --git a/doc/lispref/eval.texi b/doc/lispref/eval.texi index 064fca22ff5..74fefdb71bc 100644 --- a/doc/lispref/eval.texi +++ b/doc/lispref/eval.texi @@ -20,11 +20,12 @@ function @code{eval}. @ifnottex @menu -* Intro Eval:: Evaluation in the scheme of things. -* Forms:: How various sorts of objects are evaluated. -* Quoting:: Avoiding evaluation (to put constants in the program). -* Backquote:: Easier construction of list structure. -* Eval:: How to invoke the Lisp interpreter explicitly. +* Intro Eval:: Evaluation in the scheme of things. +* Forms:: How various sorts of objects are evaluated. +* Quoting:: Avoiding evaluation (to put constants in the program). +* Backquote:: Easier construction of list structure. +* Eval:: How to invoke the Lisp interpreter explicitly. +* Deferred Eval:: Deferred and lazy evaluation of forms. @end menu @node Intro Eval @@ -877,3 +878,115 @@ particular elements, like this: @end group @end example @end defvar + +@node Deferred Eval +@section Deferred and Lazy Evaluation + +@cindex deferred evaluation +@cindex lazy evaluation + + + Sometimes it is useful to delay the evaluation of an expression, for +example if you want to avoid to perform a time-consuming calculation +in the case that it turns out that the result is not needed in the +future of the program. Therefore, the @file{thunk} library provides +the following functions and macros: + +@cindex thunk +@defmac thunk-delay forms@dots{} +Return a @dfn{thunk} for evaluating the @var{forms}. A thunk is a +closure (@pxref{Closures}) that inherits the lexical enviroment of the +@code{thunk-delay} call. Using this macro requires +@code{lexical-binding}. +@end defmac + +@defun thunk-force thunk +Force @var{thunk} to perform the evaluation of the forms specified in +the @code{thunk-delay} that created the thunk. The result of the +evaluation of the last form is returned. The @var{thunk} also +``remembers'' that it has been forced: Any further calls of +@code{thunk-force} with the same @var{thunk} will just return the same +result without evaluating the forms again. +@end defun + +@defmac thunk-let (bindings@dots{}) forms@dots{} +This macro is analogous to @code{let} but creates ``lazy'' variable +bindings. Any binding has the form @w{@code{(@var{symbol} +@var{value-form})}}. Unlike @code{let}, the evaluation of any +@var{value-form} is deferred until the binding of the according +@var{symbol} is used for the first time when evaluating the +@var{forms}. Any @var{value-form} is evaluated at most once. Using +this macro requires @code{lexical-binding}. +@end defmac + +Example: + +@example +@group +(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))) +@end group + +@group +(f 5) +@result{} 5 +@end group + +@group +(f 12) +@print{} Calculating 1 plus 2 times 12 +@result{} 25 +@end group + +@end example + +Because of the special nature of lazily bound variables, it is an error +to set them (e.g.@: with @code{setq}). + + +@defmac thunk-let* (bindings@dots{}) forms@dots{} +This is like @code{thunk-let} but any expression in @var{bindings} is allowed +to refer to preceding bindings in this @code{thunk-let*} form. Using +this macro requires @code{lexical-binding}. +@end defmac + +@example +@group +(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)) + +@print{} Calculating z... +@print{} Calculating y... +@print{} Calculating x... +@print{} Finished calculating x +@print{} Finished calculating y +@print{} Finished calculating z +@result{} 8 + +@end group +@end example + +@code{thunk-let} and @code{thunk-let*} 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} are then replaced by an expression that calls +@code{thunk-force} with the according helper variable as the argument. +So, any code using @code{thunk-let} or @code{thunk-let*} could be +rewritten to use thunks, but in many cases using these macros results +in nicer code than using thunks explicitly. |