/usr/share/doc/r5rs-doc/r5rs/Control-features.html is in r5rs-doc 20010328-7.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 | <html lang="en">
<head>
<title>Control features - Revised(5) Scheme</title>
<meta http-equiv="Content-Type" content="text/html">
<meta name="description" content="Revised(5) Scheme">
<meta name="generator" content="makeinfo 4.13">
<link title="Top" rel="start" href="index.html#Top">
<link rel="up" href="Standard-procedures.html#Standard-procedures" title="Standard procedures">
<link rel="prev" href="Other-data-types.html#Other-data-types" title="Other data types">
<link rel="next" href="Eval.html#Eval" title="Eval">
<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
pre.display { font-family:inherit }
pre.format { font-family:inherit }
pre.smalldisplay { font-family:inherit; font-size:smaller }
pre.smallformat { font-family:inherit; font-size:smaller }
pre.smallexample { font-size:smaller }
pre.smalllisp { font-size:smaller }
span.sc { font-variant:small-caps }
span.roman { font-family:serif; font-weight:normal; }
span.sansserif { font-family:sans-serif; font-weight:normal; }
--></style>
</head>
<body>
<div class="node">
<a name="Control-features"></a>
<p>
Next: <a rel="next" accesskey="n" href="Eval.html#Eval">Eval</a>,
Previous: <a rel="previous" accesskey="p" href="Other-data-types.html#Other-data-types">Other data types</a>,
Up: <a rel="up" accesskey="u" href="Standard-procedures.html#Standard-procedures">Standard procedures</a>
<hr>
</div>
<h3 class="section">6.4 Control features</h3>
<p><a name="index-g_t_0040w_007bcontrol-features_007d-409"></a>
<!-- Intro flushed; not very a propos any more. -->
<!-- Procedures should be discussed somewhere, however. -->
<p>This chapter describes various primitive procedures which control the
flow of program execution in special ways.
The ‘<samp><span class="samp">procedure?</span></samp>’ predicate is also described here.
<div class="defun">
— procedure: <b>procedure?</b><var> obj<a name="index-procedure_003f-410"></a></var><br>
<blockquote>
<p>Returns <tt>#t</tt> if <var>obj</var> is a procedure, otherwise returns <tt>#f</tt>.
<pre class="format"><tt>(procedure? car) ==> #t
(procedure? 'car) ==> #f
(procedure? (lambda (x) (* x x)))
==> #t
(procedure? '(lambda (x) (* x x)))
==> #f
(call-with-current-continuation procedure?)
==> #t
</tt>
</pre>
</blockquote></div>
<div class="defun">
— procedure: <b>apply</b><var> proc arg1 <small class="dots">...</small> args<a name="index-apply-411"></a></var><br>
<blockquote>
<p><var>Proc</var> must be a procedure and <var>args</var> must be a list.
Calls <var>proc</var> with the elements of the list
‘<samp><span class="samp">(append (list </span><var>arg1</var><span class="samp"> ...) </span><var>args</var><span class="samp">)</span></samp>’ as the actual
arguments.
<pre class="format"><tt>(apply + (list 3 4)) ==> 7
(define compose
(lambda (f g)
(lambda args
(f (apply g args)))))
((compose sqrt *) 12 75) ==> 30
</tt>
</pre>
</blockquote></div>
<div class="defun">
— library procedure: <b>map</b><var> proc list1 list2 <small class="dots">...</small><a name="index-map-412"></a></var><br>
<blockquote>
<p>The <var>list</var>s must be lists, and <var>proc</var> must be a
procedure taking as many arguments as there are <i>list</i>s
and returning a single value. If more
than one <var>list</var> is given, then they must all be the same length.
‘<samp><span class="samp">Map</span></samp>’ applies <var>proc</var> element-wise to the elements of the
<var>list</var>s and returns a list of the results, in order.
The dynamic order in which <var>proc</var> is applied to the elements of the
<var>list</var>s is unspecified.
<pre class="format"><tt>(map cadr '((a b) (d e) (g h)))
==> (b e h)
(map (lambda (n) (expt n n))
'(1 2 3 4 5))
==> (1 4 27 256 3125)
(map + '(1 2 3) '(4 5 6)) ==> (5 7 9)
(let ((count 0))
(map (lambda (ignored)
(set! count (+ count 1))
count)
'(a b))) ==> (1 2) </tt><var>or</var><tt> (2 1)
</tt>
</pre>
</blockquote></div>
<div class="defun">
— library procedure: <b>for-each</b><var> proc list1 list2 <small class="dots">...</small><a name="index-for_002deach-413"></a></var><br>
<blockquote>
<p>The arguments to ‘<samp><span class="samp">for-each</span></samp>’ are like the arguments to ‘<samp><span class="samp">map</span></samp>’, but
‘<samp><span class="samp">for-each</span></samp>’ calls <var>proc</var> for its side effects rather than for its
values. Unlike ‘<samp><span class="samp">map</span></samp>’, ‘<samp><span class="samp">for-each</span></samp>’ is guaranteed to call <var>proc</var> on
the elements of the <var>list</var>s in order from the first element(s) to the
last, and the value returned by ‘<samp><span class="samp">for-each</span></samp>’ is unspecified.
<pre class="format"><tt>(let ((v (make-vector 5)))
(for-each (lambda (i)
(vector-set! v i (* i i)))
'(0 1 2 3 4))
v) ==> #(0 1 4 9 16)
</tt>
</pre>
</blockquote></div>
<div class="defun">
— library procedure: <b>force</b><var> promise<a name="index-force-414"></a></var><br>
<blockquote>
<p>Forces the value of <var>promise</var> (see <code>delay</code>,
<a name="index-g_t_0040w_007bdelay_007d-415"></a>section see <a href="Delayed-evaluation.html#Delayed-evaluation">Delayed evaluation</a>). If no value has been computed for
<a name="index-g_t_0040w_007bpromise_007d-416"></a>the promise, then a value is computed and returned. The value of the
promise is cached (or “memoized”) so that if it is forced a second
time, the previously computed value is returned.
<!-- without any recomputation. -->
<!-- [As pointed out by Marc Feeley, the "without any recomputation" -->
<!-- isn't necessarily true. -Will] -->
<pre class="format"><tt>(force (delay (+ 1 2))) ==> 3
(let ((p (delay (+ 1 2))))
(list (force p) (force p)))
==> (3 3)
(define a-stream
(letrec ((next
(lambda (n)
(cons n (delay (next (+ n 1)))))))
(next 0)))
(define head car)
(define tail
(lambda (stream) (force (cdr stream))))
(head (tail (tail a-stream)))
==> 2
</tt>
</pre>
<p>‘<samp><span class="samp">Force</span></samp>’ and ‘<samp><span class="samp">delay</span></samp>’ are mainly intended for programs written in
functional style. The following examples should not be considered to
illustrate good programming style, but they illustrate the property that
only one value is computed for a promise, no matter how many times it is
forced.
<!-- the value of a promise is computed at most once. -->
<!-- [As pointed out by Marc Feeley, it may be computed more than once, -->
<!-- but as I observed we can at least insist that only one value be -->
<!-- used! - Will] -->
<pre class="format"><tt>(define count 0)
(define p
(delay (begin (set! count (+ count 1))
(if (> count x)
count
(force p)))))
(define x 5)
p ==> </tt><tt>a promise
(force p) ==> 6
p ==> </tt><tt>a promise, still
(begin (set! x 10)
(force p)) ==> 6
</tt>
</pre>
<p>Here is a possible implementation of ‘<samp><span class="samp">delay</span></samp>’ and ‘<samp><span class="samp">force</span></samp>’.
Promises are implemented here as procedures of no arguments,
and ‘<samp><span class="samp">force</span></samp>’ simply calls its argument:
<pre class="format"><tt>(define force
(lambda (object)
(object)))
</tt>
</pre>
<p>We define the expression
<pre class="format"><tt>(delay </tt><span class="roman"><expression></span><tt>)
</tt>
</pre>
<p>to have the same meaning as the procedure call
<pre class="format"><tt>(make-promise (lambda () </tt><span class="roman"><expression></span><tt>))</tt>
</pre>
<p>as follows
<pre class="format"><tt>(define-syntax delay
(syntax-rules ()
((delay expression)
(make-promise (lambda () expression))))),
</tt>
</pre>
<p>where ‘<samp><span class="samp">make-promise</span></samp>’ is defined as follows:
<!-- \begin{scheme} -->
<!-- (define make-promise -->
<!-- (lambda (proc) -->
<!-- (let ((already-run? \schfalse) (result \schfalse)) -->
<!-- (lambda () -->
<!-- (cond ((not already-run?) -->
<!-- (set! result (proc)) -->
<!-- (set! already-run? \schtrue))) -->
<!-- result))))% -->
<!-- \end{scheme} -->
<pre class="format"><tt>(define make-promise
(lambda (proc)
(let ((result-ready? #f)
(result #f))
(lambda ()
(if result-ready?
result
(let ((x (proc)))
(if result-ready?
result
(begin (set! result-ready? #t)
(set! result x)
result))))))))
</tt>
</pre>
<blockquote>
<em>Rationale:</em>
A promise may refer to its own value, as in the last example above.
Forcing such a promise may cause the promise to be forced a second time
before the value of the first force has been computed.
This complicates the definition of ‘<samp><span class="samp">make-promise</span></samp>’.
</blockquote>
<p>Various extensions to this semantics of ‘<samp><span class="samp">delay</span></samp>’ and ‘<samp><span class="samp">force</span></samp>’
are supported in some implementations:
<ul>
<li>Calling ‘<samp><span class="samp">force</span></samp>’ on an object that is not a promise may simply
return the object.
<li>It may be the case that there is no means by which a promise can be
operationally distinguished from its forced value. That is, expressions
like the following may evaluate to either <tt>#t</tt> or to <tt>#f</tt>,
depending on the implementation:
<pre class="format"><tt>(eqv? (delay 1) 1) ==> </tt><em>unspecified</em><tt>
(pair? (delay (cons 1 2))) ==> </tt><em>unspecified</em>
</pre>
<li>Some implementations may implement “implicit forcing,” where
the value of a promise is forced by primitive procedures like ‘<samp><span class="samp">cdr</span></samp>’
and ‘<samp><span class="samp">+</span></samp>’:
<pre class="format"><tt>(+ (delay (* 3 7)) 13) ==> 34
</tt>
</pre>
</ul>
</blockquote></div>
<div class="defun">
— procedure: <b>call-with-current-continuation</b><var> proc<a name="index-call_002dwith_002dcurrent_002dcontinuation-417"></a></var><br>
<blockquote>
<p><var>Proc</var> must be a procedure of one
argument. The procedure ‘<samp><span class="samp">call-with-current-continuation</span></samp>’ packages
up the current continuation (see the rationale below) as an “escape
procedure” and passes it as an argument to
<a name="index-g_t_0040w_007bescape-procedure_007d-418"></a><var>proc</var>. The escape procedure is a Scheme procedure that, if it is
later called, will abandon whatever continuation is in effect at that later
time and will instead use the continuation that was in effect
when the escape procedure was created. Calling the escape procedure
may cause the invocation of <var>before</var> and <var>after</var> thunks installed using
<code>dynamic-wind</code>.
<a name="index-g_t_0040w_007bdynamic_002dwind_007d-419"></a>
The escape procedure accepts the same number of arguments as the continuation to
the original call to <tt>call-with-current-continuation</tt>.
Except for continuations created by the ‘<samp><span class="samp">call-with-values</span></samp>’
procedure, all continuations take exactly one value. The
effect of passing no value or more than one value to continuations
that were not created by <tt>call-with-values</tt> is unspecified.
<p>The escape procedure that is passed to <var>proc</var> has
unlimited extent just like any other procedure in Scheme. It may be stored
in variables or data structures and may be called as many times as desired.
<p>The following examples show only the most common ways in which
‘<samp><span class="samp">call-with-current-continuation</span></samp>’ is used. If all real uses were as
simple as these examples, there would be no need for a procedure with
the power of ‘<samp><span class="samp">call-with-current-continuation</span></samp>’.
<pre class="format"><tt>(call-with-current-continuation
(lambda (exit)
(for-each (lambda (x)
(if (negative? x)
(exit x)))
'(54 0 37 -3 245 19))
#t)) ==> -3
(define list-length
(lambda (obj)
(call-with-current-continuation
(lambda (return)
(letrec ((r
(lambda (obj)
(cond ((null? obj) 0)
((pair? obj)
(+ (r (cdr obj)) 1))
(else (return #f))))))
(r obj))))))
(list-length '(1 2 3 4)) ==> 4
(list-length '(a b . c)) ==> #f
</tt>
</pre>
<blockquote>
<em>Rationale:</em>
<p>A common use of ‘<samp><span class="samp">call-with-current-continuation</span></samp>’ is for
structured, non-local exits from loops or procedure bodies, but in fact
‘<samp><span class="samp">call-with-current-continuation</span></samp>’ is extremely useful for implementing a
wide variety of advanced control structures.
<p>Whenever a Scheme expression is evaluated there is a
<dfn>continuation</dfn> wanting the result of the expression. The continuation
<a name="index-g_t_0040w_007bcontinuation_007d-420"></a>represents an entire (default) future for the computation. If the expression is
evaluated at top level, for example, then the continuation might take the
result, print it on the screen, prompt for the next input, evaluate it, and
so on forever. Most of the time the continuation includes actions
specified by user code, as in a continuation that will take the result,
multiply it by the value stored in a local variable, add seven, and give
the answer to the top level continuation to be printed. Normally these
ubiquitous continuations are hidden behind the scenes and programmers do not
think much about them. On rare occasions, however, a programmer may
need to deal with continuations explicitly.
‘<samp><span class="samp">Call-with-current-continuation</span></samp>’ allows Scheme programmers to do
that by creating a procedure that acts just like the current
continuation.
<p>Most programming languages incorporate one or more special-purpose
escape constructs with names like <tt>exit</tt>, ‘<samp><span class="samp">return</span></samp>’<!-- /@w -->, or
even <tt>goto</tt>. In 1965, however, Peter Landin [Landin65]
invented a general purpose escape operator called the J-operator. John
Reynolds [Reynolds72] described a simpler but equally powerful
construct in 1972. The ‘<samp><span class="samp">catch</span></samp>’ special form described by Sussman
and Steele in the 1975 report on Scheme is exactly the same as
Reynolds's construct, though its name came from a less general construct
in MacLisp. Several Scheme implementors noticed that the full power of the
<code>catch</code> construct could be provided by a procedure instead of by a
<a name="index-g_t_0040w_007bcatch_007d-421"></a>special syntactic construct, and the name
‘<samp><span class="samp">call-with-current-continuation</span></samp>’ was coined in 1982. This name is
descriptive, but opinions differ on the merits of such a long name, and
some people use the name <code>call/cc</code> instead.
<a name="index-g_t_0040w_007bcall_002fcc_007d-422"></a></blockquote>
</blockquote></div>
<div class="defun">
— procedure: <b>values</b><var> obj <small class="dots">...</small><a name="index-values-423"></a></var><br>
<blockquote>
<p>Delivers all of its arguments to its continuation.
Except for continuations created by the <code>call-with-values</code>
<a name="index-g_t_0040w_007bcall_002dwith_002dvalues_007d-424"></a>procedure, all continuations take exactly one value.
<tt>Values</tt> might be defined as follows:
<pre class="format"><tt>(define (values . things)
(call-with-current-continuation
(lambda (cont) (apply cont things))))
</tt>
</pre>
</blockquote></div>
<div class="defun">
— procedure: <b>call-with-values</b><var> producer consumer<a name="index-call_002dwith_002dvalues-425"></a></var><br>
<blockquote>
<p>Calls its <var>producer</var> argument with no values and
a continuation that, when passed some values, calls the
<var>consumer</var> procedure with those values as arguments.
The continuation for the call to <var>consumer</var> is the
continuation of the call to <tt>call-with-values</tt>.
<pre class="format"><tt>(call-with-values (lambda () (values 4 5))
(lambda (a b) b))
==> 5
(call-with-values * -) ==> -1
</tt>
</pre>
</blockquote></div>
<div class="defun">
— procedure: <b>dynamic-wind</b><var> before thunk after<a name="index-dynamic_002dwind-426"></a></var><br>
<blockquote>
<p>Calls <var>thunk</var> without arguments, returning the result(s) of this call.
<var>Before</var> and <var>after</var> are called, also without arguments, as required
by the following rules (note that in the absence of calls to continuations
captured using <code>call-with-current-continuation</code> the three arguments are
<a name="index-g_t_0040w_007bcall_002dwith_002dcurrent_002dcontinuation_007d-427"></a>called once each, in order). <var>Before</var> is called whenever execution
enters the dynamic extent of the call to <var>thunk</var> and <var>after</var> is called
whenever it exits that dynamic extent. The dynamic extent of a procedure
call is the period between when the call is initiated and when it
returns. In Scheme, because of ‘<samp><span class="samp">call-with-current-continuation</span></samp>’, the
dynamic extent of a call may not be a single, connected time period.
It is defined as follows:
<ul>
<li>The dynamic extent is entered when execution of the body of the
called procedure begins.
<li>The dynamic extent is also entered when execution is not within
the dynamic extent and a continuation is invoked that was captured
(using ‘<samp><span class="samp">call-with-current-continuation</span></samp>’) during the dynamic extent.
<li>It is exited when the called procedure returns.
<li>It is also exited when execution is within the dynamic extent and
a continuation is invoked that was captured while not within the
dynamic extent.
</ul>
<p>If a second call to ‘<samp><span class="samp">dynamic-wind</span></samp>’ occurs within the dynamic extent of the
call to <var>thunk</var> and then a continuation is invoked in such a way that the
<var>after</var>s from these two invocations of ‘<samp><span class="samp">dynamic-wind</span></samp>’ are both to be
called, then the <var>after</var> associated with the second (inner) call to
‘<samp><span class="samp">dynamic-wind</span></samp>’ is called first.
<p>If a second call to ‘<samp><span class="samp">dynamic-wind</span></samp>’ occurs within the dynamic extent of the
call to <var>thunk</var> and then a continuation is invoked in such a way that the
<var>before</var>s from these two invocations of ‘<samp><span class="samp">dynamic-wind</span></samp>’ are both to be
called, then the <var>before</var> associated with the first (outer) call to
‘<samp><span class="samp">dynamic-wind</span></samp>’ is called first.
<p>If invoking a continuation requires calling the <var>before</var> from one call
to ‘<samp><span class="samp">dynamic-wind</span></samp>’ and the <var>after</var> from another, then the <var>after</var>
is called first.
<p>The effect of using a captured continuation to enter or exit the dynamic
extent of a call to <var>before</var> or <var>after</var> is undefined.
<pre class="format"><tt>(let ((path '())
(c #f))
(let ((add (lambda (s)
(set! path (cons s path)))))
(dynamic-wind
(lambda () (add 'connect))
(lambda ()
(add (call-with-current-continuation
(lambda (c0)
(set! c c0)
'talk1))))
(lambda () (add 'disconnect)))
(if (< (length path) 4)
(c 'talk2)
(reverse path))))
==> (connect talk1 disconnect
connect talk2 disconnect)
</tt>
</pre>
</blockquote></div>
</body></html>
|