diff options
author | Kevin Ryde <user42@zip.com.au> | 2004-02-14 23:04:55 +0000 |
---|---|---|
committer | Kevin Ryde <user42@zip.com.au> | 2004-02-14 23:04:55 +0000 |
commit | 0e43f514aa3d58046aa105ca73312c7c439f4c76 (patch) | |
tree | 8e08d130c5b2b92198825f7aebd642234c7e744f | |
parent | 0c7d588a7a9fd6407124fdf54f28760063c94ef2 (diff) | |
download | guile-0e43f514aa3d58046aa105ca73312c7c439f4c76.tar.gz |
(while do): Expand and clarify `do', in
particular note iterating binds fresh locations, rather than values
"stored".
-rw-r--r-- | doc/ref/scheme-control.texi | 73 |
1 files changed, 61 insertions, 12 deletions
diff --git a/doc/ref/scheme-control.texi b/doc/ref/scheme-control.texi index 96f2daa08..7d7662c53 100644 --- a/doc/ref/scheme-control.texi +++ b/doc/ref/scheme-control.texi @@ -299,18 +299,67 @@ Scheme programs is normally expressed using recursion. Nevertheless, R5RS defines a construct for programming loops, calling @code{do}. In addition, Guile has an explicit looping syntax called @code{while}. -@deffn syntax do ((variable1 init1 step1) @dots{}) (test expr @dots{}) command @dots{} -The @var{init} expressions are evaluated and the @var{variables} are -bound to their values. Then looping starts with testing the @var{test} -expression. If @var{test} evaluates to a true value, the @var{expr} -following the @var{test} are evaluated and the value of the last -@var{expr} is returned as the value of the @code{do} expression. If -@var{test} evaluates to false, the @var{command}s are evaluated in -order, the @var{step}s are evaluated and stored into the @var{variables} -and the next iteration starts. - -Any of the @var{step} expressions may be omitted, so that the -corresponding variable is not changed during looping. +@deffn syntax do ((variable init [step]) @dots{}) (test [expr @dots{}]) body @dots{} +Bind @var{variable}s and evaluate @var{body} until @var{test} is true. +The return value is the last @var{expr} after @var{test}, if given. A +simple example will illustrate the basic form, + +@example +(do ((i 1 (1+ i))) + ((> i 4)) + (display i)) +@print{} 1234 +@end example + +@noindent +Or with two variables and a final return value, + +@example +(do ((i 1 (1+ i)) + (p 3 (* 3 p))) + ((> i 4) + p) + (format #t "3**~s is ~s\n" i p)) +@print{} +3**1 is 3 +3**2 is 9 +3**3 is 27 +3**4 is 81 +@result{} +789 +@end example + +The @var{variable} bindings are established like a @code{let}, in that +the expressions are all evaluated and then all bindings made. When +iterating, the optional @var{step} expressions are evaluated with the +previous bindings in scope, then new bindings all made. + +The @var{test} expression is a termination condition. Looping stops +when the @var{test} is true. It's evaluated before running the +@var{body} each time, so if it's true the first time then @var{body} +is not run at all. + +The optional @var{expr}s after the @var{test} are evaluated at the end +of looping, with the final @var{variable} bindings available. The +last @var{expr} gives the return value, or if there are no @var{expr}s +the return value is unspecified. + +Each iteration establishes bindings to fresh locations for the +@var{variable}s, like a new @code{let} for each iteration. This is +done for @var{variable}s without @var{step} expressions too. The +following illustrates this, showing how a new @code{i} is captured by +the @code{lambda} in each iteration (@pxref{About Closure,, The +Concept of Closure}). + +@example +(define lst '()) +(do ((i 1 (1+ i))) + ((> i 4)) + (set! lst (cons (lambda () i) lst))) +(map (lambda (proc) (proc)) lst) +@result{} +(4 3 2 1) +@end example @end deffn @deffn syntax while cond body @dots{} |