1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
|
<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<!--
Generated from r6rs-lib.tex by tex2page, v 20070803
(running on MzScheme 371, unix),
(c) Dorai Sitaram,
http://www.ccs.neu.edu/~dorai/tex2page/tex2page-doc.html
-->
<head>
<title>
r6rs-lib
</title>
<link rel="stylesheet" type="text/css" href="r6rs-lib-Z-S.css" title=default>
<meta name=robots content="index,follow">
</head>
<body>
<div id=slidecontent>
<div align=right class=navigation>[Go to <span><a href="r6rs-lib.html">first</a>, <a href="r6rs-lib-Z-H-5.html">previous</a></span><span>, <a href="r6rs-lib-Z-H-7.html">next</a></span> page<span>; </span><span><a href="r6rs-lib-Z-H-1.html#node_toc_start">contents</a></span><span><span>; </span><a href="r6rs-lib-Z-H-21.html#node_index_start">index</a></span>]</div>
<p></p>
<a name="node_chap_5"></a>
<h1 class=chapter>
<div class=chapterheading><a href="r6rs-lib-Z-H-1.html#node_toc_node_chap_5">Chapter 5</a></div><br>
<a href="r6rs-lib-Z-H-1.html#node_toc_node_chap_5">Control structures</a></h1>
<p></p>
<p>
This chapter describes the <tt>(rnrs control (6))</tt><a name="node_idx_252"></a>library, which
provides useful control structures.</p>
<p>
</p>
<p></p>
<div align=left><tt>(<a name="node_idx_254"></a>when<i> <test> <expression<sub>1</sub>> <expression<sub>2</sub>> <tt>...</tt></i>)</tt> syntax </div>
<div align=left><tt>(<a name="node_idx_256"></a>unless<i> <test> <expression<sub>1</sub>> <expression<sub>2</sub>> <tt>...</tt></i>)</tt> syntax </div>
<p>
<em>Syntax: </em><Test> must be an expression.</p>
<p>
<em>Semantics: </em>A <tt>when</tt> expression is evaluated by evaluating the
<test> expression. If <test> evaluates to a true value,
the remaining <expression>s are evaluated in order, and the
results of the last <expression> are returned as the
results of the entire <tt>when</tt> expression. Otherwise, the <tt>when</tt> expression returns unspecified values. An <tt>unless</tt>
expression is evaluated by evaluating the <test> expression.
If <test> evaluates to <tt>#f</tt>, the remaining
<expression>s are evaluated in order, and the results of the
last <expression> are returned as the results of the
entire <tt>unless</tt> expression. Otherwise, the <tt>unless</tt> expression
returns unspecified values.</p>
<p>
The final <expression> is in tail context if the <tt>when</tt> or
<tt>unless</tt> form is itself in tail context.</p>
<p>
</p>
<tt>(when (> 3 2) ’greater) ⇒ greater<br>
(when (< 3 2) ’greater) ⇒ <em>unspecified</em><br>
(unless (> 3 2) ’less) ⇒ <em>unspecified</em><br>
(unless (< 3 2) ’less) ⇒ less<br>
<p></tt></p>
<p>
The <tt>when</tt> and <tt>unless</tt> expressions are derived forms. They
could be defined by the following macros:</p>
<p>
</p>
<tt>(define-syntax <tt>when</tt><br>
(syntax-rules ()<br>
((when test result1 result2 ...)<br>
(if test<br>
(begin result1 result2 ...)))))<br>
<br>
(define-syntax <tt>unless</tt><br>
(syntax-rules ()<br>
((unless test result1 result2 ...)<br>
(if (not test)<br>
(begin result1 result2 ...)))))<br>
<p></tt></p>
<p>
</p>
<p></p>
<p>
</p>
<p class=noindent></p>
<div align=left><tt>(do ((<variable<sub>1</sub>> <init<sub>1</sub>> <step<sub>1</sub>>)</tt> syntax </div>
<a name="node_idx_258"></a><tt><tt>...</tt>)<br>
(<test> <expression> <tt>...</tt>)<br>
<command> <tt>...</tt>)</tt><p>
<em>Syntax: </em>The <init>s, <step>s, <test>s, and <command>s must be
expressions. The <variable>s must be pairwise distinct variables.</p>
<p>
<em>Semantics: </em>The <tt>do</tt> expression is an iteration construct. It specifies a set of variables to
be bound, how they are to be initialized at the start, and how they are
to be updated on each iteration.</p>
<p>
A <tt>do</tt> expression is evaluated as follows:
The <init> expressions are evaluated (in some unspecified order),
the <variable>s are bound to fresh locations, the results of the
<init> expressions are stored in the bindings of the
<variable>s, and then the iteration phase begins.</p>
<p>
Each iteration begins by evaluating <test>; if the result is
<tt>#f</tt>, then the <command>s
are evaluated in order for effect, the <step>
expressions are evaluated in some unspecified order, the
<variable>s are bound to fresh locations holding the results,
and the next iteration begins.</p>
<p>
If <test> evaluates to a true value, the
<expression>s are evaluated from left to right and the values of
the last <expression> are returned. If no <expression>s
are present, then the <tt>do</tt> expression returns unspecified values.</p>
<p>
The region<a name="node_idx_260"></a>of the binding of a <variable>
consists of the entire <tt>do</tt> expression except for the <init>s.</p>
<p>
A <step> may be omitted, in which case the effect is the
same as if <tt>(<variable> <init> <variable>)</tt> had
been written instead of <tt>(<variable> <init>)</tt>.</p>
<p>
If a <tt>do</tt> expression appears in a tail context, the
<expression>s are a <tail sequence> in the sense of report
section on “Tail calls and tail contexts”,
i.e., the last <expression> is also in a tail context.</p>
<p>
</p>
<tt>(do ((vec (make-vector 5))<br>
(i 0 (+ i 1)))<br>
((= i 5) vec)<br>
(vector-set! vec i i)) ⇒ #(0 1 2 3 4)<br>
<br>
(let ((x ’(1 3 5 7 9)))<br>
(do ((x x (cdr x))<br>
(sum 0 (+ sum (car x))))<br>
((null? x) sum))) ⇒ 25<p></tt></p>
<p>
The following definition
of <tt>do</tt> uses a trick to expand the variable clauses.</p>
<p>
</p>
<tt>(define-syntax <tt>do</tt><br>
(syntax-rules ()<br>
((do ((var init step ...) ...)<br>
(test expr ...)<br>
command ...)<br>
(letrec<br>
((loop<br>
(lambda (var ...)<br>
(if test<br>
(begin<br>
<tt>#f</tt> ; avoid empty begin<br>
expr ...)<br>
(begin<br>
command<br>
...<br>
(loop (do "step" var step ...)<br>
...))))))<br>
(loop init ...)))<br>
((do "step" x)<br>
x)<br>
((do "step" x y)<br>
y)))<p></tt></p>
<p>
</p>
<p>
</p>
<p></p>
<div align=left><tt>(<a name="node_idx_262"></a>case-lambda<i> <case-lambda clause> <tt>...</tt></i>)</tt> syntax </div>
<p>
<em>Syntax: </em>Each <case-lambda clause> must be of the form
</p>
<tt>(<formals> <body>)<p></tt></p>
<p>
<Formals> must be as in a <tt>lambda</tt> form
(report section on “Procedures”), and <body> is as described in
report section on “Bodies and sequences”.</p>
<p>
<em>Semantics: </em>A <tt>case-lambda</tt> expression evaluates to a procedure.
This procedure, when applied, tries to match its arguments to the
<case-lambda clause>s in order. The arguments match a clause if one of the
following conditions is fulfilled:
</p>
<ul>
<li><p><Formals> has the form <tt>(<variable> <tt>...</tt>)</tt>
and the number of arguments is the same as the number of formal
parameters in <formals>.
</p>
<li><p><Formals> has the form<br>
<tt>(<variable<sub>1</sub>> <tt>...</tt><variable<sub><em>n</em></sub>> . <variable<sub><em>n</em>+1</sub>)>
</tt><br>
and the number of arguments is at least <em>n</em>.
</p>
<li><p><Formals> has the form <tt><variable></tt>.
</p>
</ul><p>
For the first clause matched by the arguments, the variables of the
<formals> are bound to fresh locations containing the
argument values in the same arrangement as with <tt>lambda</tt>.</p>
<p>
The last expression of a <body> in a <tt>case-lambda
expression</tt> is in tail context.</p>
<p>
If the arguments match none of the clauses, an exception with condition
type <tt>&assertion</tt> is raised.</p>
<p>
</p>
<tt>(define foo<br>
(case-lambda <br>
(() ’zero)<br>
((x) (list ’one x))<br>
((x y) (list ’two x y))<br>
((a b c d . e) (list ’four a b c d e))<br>
(rest (list ’rest rest))))<br>
<br>
(foo) ⇒ zero<br>
(foo 1) ⇒ (one 1)<br>
(foo 1 2) ⇒ (two 1 2)<br>
(foo 1 2 3) ⇒ (rest (1 2 3))<br>
(foo 1 2 3 4) ⇒ (four 1 2 3 4 ())<br>
<p></tt></p>
<p>
The <tt>case-lambda</tt> keyword
can be defined in terms of <tt>lambda</tt> by the following macros:
</p>
<tt>(define-syntax <tt>case-lambda</tt><br>
(syntax-rules ()<br>
((_ (fmls b1 b2 ...))<br>
(lambda fmls b1 b2 ...))<br>
((_ (fmls b1 b2 ...) ...)<br>
(lambda args<br>
(let ((n (length args)))<br>
(case-lambda-help args n<br>
(fmls b1 b2 ...) ...))))))<br>
<br>
(define-syntax case-lambda-help<br>
(syntax-rules ()<br>
((_ args n)<br>
(assertion-violation <tt>#f</tt><br>
"unexpected number of arguments"))<br>
((_ args n ((x ...) b1 b2 ...) more ...)<br>
(if (= n (length ’(x ...)))<br>
(apply (lambda (x ...) b1 b2 ...) args)<br>
(case-lambda-help args n more ...)))<br>
((_ args n ((x1 x2 ... . r) b1 b2 ...) more ...)<br>
(if (>= n (length ’(x1 x2 ...)))<br>
(apply (lambda (x1 x2 ... . r) b1 b2 ...)<br>
args)<br>
(case-lambda-help args n more ...)))<br>
((_ args n (r b1 b2 ...) more ...)<br>
(apply (lambda r b1 b2 ...) args))))<br>
<p></tt>
</p>
<p></p>
<p>
</p>
<p></p>
<div class=smallskip></div>
<p style="margin-top: 0pt; margin-bottom: 0pt">
<div align=right class=navigation>[Go to <span><a href="r6rs-lib.html">first</a>, <a href="r6rs-lib-Z-H-5.html">previous</a></span><span>, <a href="r6rs-lib-Z-H-7.html">next</a></span> page<span>; </span><span><a href="r6rs-lib-Z-H-1.html#node_toc_start">contents</a></span><span><span>; </span><a href="r6rs-lib-Z-H-21.html#node_index_start">index</a></span>]</div>
</p>
<p></p>
</div>
</body>
</html>
|