aboutsummaryrefslogtreecommitdiffstats
path: root/doc
diff options
context:
space:
mode:
authorMichael Heerdegen2017-11-02 18:45:34 +0100
committerMichael Heerdegen2017-12-01 08:54:05 +0100
commitcc58d4de56e362f5e017d0607986b2962ee47fc1 (patch)
tree3b2427fc07973dd598424ed185b5a36bc0d69be9 /doc
parentef183144add2b92359a9ade2ec0b28681b26956b (diff)
downloademacs-cc58d4de56e362f5e017d0607986b2962ee47fc1.tar.gz
emacs-cc58d4de56e362f5e017d0607986b2962ee47fc1.zip
Add macros `thunk-let' and `thunk-let*'
* lisp/emacs-lisp/thunk.el (thunk-let, thunk-let*): New macros. * test/lisp/emacs-lisp/thunk-tests.el: (thunk-let-basic-test, thunk-let*-basic-test) (thunk-let-bound-vars-cant-be-set-test) (thunk-let-laziness-test, thunk-let*-laziness-test) (thunk-let-bad-binding-test): New tests for `thunk-let' and `thunk-let*. * doc/lispref/eval.texi (Deferred Eval): New section. * doc/lispref/elisp.texi: Update menu.
Diffstat (limited to 'doc')
-rw-r--r--doc/lispref/elisp.texi1
-rw-r--r--doc/lispref/eval.texi123
2 files changed, 119 insertions, 5 deletions
diff --git a/doc/lispref/elisp.texi b/doc/lispref/elisp.texi
index c7525945845..a271749e044 100644
--- a/doc/lispref/elisp.texi
+++ b/doc/lispref/elisp.texi
@@ -455,6 +455,7 @@ Evaluation
455 the program). 455 the program).
456* Backquote:: Easier construction of list structure. 456* Backquote:: Easier construction of list structure.
457* Eval:: How to invoke the Lisp interpreter explicitly. 457* Eval:: How to invoke the Lisp interpreter explicitly.
458* Deferred Eval:: Deferred and lazy evaluation of forms.
458 459
459Kinds of Forms 460Kinds of Forms
460 461
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}.
20 20
21@ifnottex 21@ifnottex
22@menu 22@menu
23* Intro Eval:: Evaluation in the scheme of things. 23* Intro Eval:: Evaluation in the scheme of things.
24* Forms:: How various sorts of objects are evaluated. 24* Forms:: How various sorts of objects are evaluated.
25* Quoting:: Avoiding evaluation (to put constants in the program). 25* Quoting:: Avoiding evaluation (to put constants in the program).
26* Backquote:: Easier construction of list structure. 26* Backquote:: Easier construction of list structure.
27* Eval:: How to invoke the Lisp interpreter explicitly. 27* Eval:: How to invoke the Lisp interpreter explicitly.
28* Deferred Eval:: Deferred and lazy evaluation of forms.
28@end menu 29@end menu
29 30
30@node Intro Eval 31@node Intro Eval
@@ -877,3 +878,115 @@ particular elements, like this:
877@end group 878@end group
878@end example 879@end example
879@end defvar 880@end defvar
881
882@node Deferred Eval
883@section Deferred and Lazy Evaluation
884
885@cindex deferred evaluation
886@cindex lazy evaluation
887
888
889 Sometimes it is useful to delay the evaluation of an expression, for
890example if you want to avoid to perform a time-consuming calculation
891in the case that it turns out that the result is not needed in the
892future of the program. Therefore, the @file{thunk} library provides
893the following functions and macros:
894
895@cindex thunk
896@defmac thunk-delay forms@dots{}
897Return a @dfn{thunk} for evaluating the @var{forms}. A thunk is a
898closure (@pxref{Closures}) that inherits the lexical enviroment of the
899@code{thunk-delay} call. Using this macro requires
900@code{lexical-binding}.
901@end defmac
902
903@defun thunk-force thunk
904Force @var{thunk} to perform the evaluation of the forms specified in
905the @code{thunk-delay} that created the thunk. The result of the
906evaluation of the last form is returned. The @var{thunk} also
907``remembers'' that it has been forced: Any further calls of
908@code{thunk-force} with the same @var{thunk} will just return the same
909result without evaluating the forms again.
910@end defun
911
912@defmac thunk-let (bindings@dots{}) forms@dots{}
913This macro is analogous to @code{let} but creates ``lazy'' variable
914bindings. Any binding has the form @w{@code{(@var{symbol}
915@var{value-form})}}. Unlike @code{let}, the evaluation of any
916@var{value-form} is deferred until the binding of the according
917@var{symbol} is used for the first time when evaluating the
918@var{forms}. Any @var{value-form} is evaluated at most once. Using
919this macro requires @code{lexical-binding}.
920@end defmac
921
922Example:
923
924@example
925@group
926(defun f (number)
927 (thunk-let ((derived-number
928 (progn (message "Calculating 1 plus 2 times %d" number)
929 (1+ (* 2 number)))))
930 (if (> number 10)
931 derived-number
932 number)))
933@end group
934
935@group
936(f 5)
937@result{} 5
938@end group
939
940@group
941(f 12)
942@print{} Calculating 1 plus 2 times 12
943@result{} 25
944@end group
945
946@end example
947
948Because of the special nature of lazily bound variables, it is an error
949to set them (e.g.@: with @code{setq}).
950
951
952@defmac thunk-let* (bindings@dots{}) forms@dots{}
953This is like @code{thunk-let} but any expression in @var{bindings} is allowed
954to refer to preceding bindings in this @code{thunk-let*} form. Using
955this macro requires @code{lexical-binding}.
956@end defmac
957
958@example
959@group
960(thunk-let* ((x (prog2 (message "Calculating x...")
961 (+ 1 1)
962 (message "Finished calculating x")))
963 (y (prog2 (message "Calculating y...")
964 (+ x 1)
965 (message "Finished calculating y")))
966 (z (prog2 (message "Calculating z...")
967 (+ y 1)
968 (message "Finished calculating z")))
969 (a (prog2 (message "Calculating a...")
970 (+ z 1)
971 (message "Finished calculating a"))))
972 (* z x))
973
974@print{} Calculating z...
975@print{} Calculating y...
976@print{} Calculating x...
977@print{} Finished calculating x
978@print{} Finished calculating y
979@print{} Finished calculating z
980@result{} 8
981
982@end group
983@end example
984
985@code{thunk-let} and @code{thunk-let*} use thunks implicitly: their
986expansion creates helper symbols and binds them to thunks wrapping the
987binding expressions. All references to the original variables in the
988body @var{forms} are then replaced by an expression that calls
989@code{thunk-force} with the according helper variable as the argument.
990So, any code using @code{thunk-let} or @code{thunk-let*} could be
991rewritten to use thunks, but in many cases using these macros results
992in nicer code than using thunks explicitly.