9.4 Continuations
See Sub-expression Evaluation and Continuations and Prompts, Delimited Continuations, and Barriers for general
information about continuations. Racket’s support for prompts and
composable continuations most closely resembles Dorai Sitaram’s
% and fcontrol operator [Sitaram93].
Racket installs a continuation barrier around evaluation in the
following contexts, preventing full-continuation jumps into the
evaluation context protected by the barrier:
In addition, extensions of Racket may install barriers in
additional contexts. Finally,
call-with-continuation-barrier applies a thunk barrier
between the application and the current continuation.
The handler argument specifies a handler procedure to be
called in tail position with respect to the
call-with-continuation-prompt call when the installed prompt
is the target of an abort-current-continuation call with
prompt-tag; the remaining arguments of
abort-current-continuation are supplied to the handler
procedure. If handler is #f, the default handler
accepts a single abort-thunk argument and calls
(call-with-continuation-prompt abort-thunk prompt-tag #f);
that is, the default handler re-installs the prompt and continues with
a given thunk.
Resets the current continuation to that of the nearest prompt tagged
by
prompt-tag in the current continuation; if no such prompt exists,
the
exn:fail:contract:continuation exception is raised. The
vs are delivered
as arguments to the target prompt’s handler procedure.
The protocol for vs supplied to an abort is specific to the
prompt-tag. When abort-current-continuation is used with
(default-continuation-prompt-tag), generally, a single thunk
should be supplied that is suitable for use with the default prompt
handler. Similarly, when call-with-continuation-prompt is
used with (default-continuation-prompt-tag), the associated
handler should generally accept a single thunk argument.
Creates a prompt tag that is not
equal? to the result of any
other value (including prior or future results from
make-continuation-prompt-tag). The optional
sym
argument, if supplied, is used when printing the prompt tag.
Returns a constant prompt tag for which a prompt is installed at the
start of every thread’s continuation; the handler for each thread’s
initial prompt accepts any number of values and returns. The result of
default-continuation-prompt-tag is the default tag for
any procedure that accepts a prompt tag.
Captures the current continuation up to the nearest prompt tagged by
prompt-tag; if no such prompt exists, the
exn:fail:contract:continuation exception is raised. The truncated continuation
includes only continuation marks and
dynamic-wind frames
installed since the prompt.
The capture continuation is delivered to proc, which is
called in tail position with respect to the
call-with-current-continuation call.
If the continuation argument to proc is ever applied, then it
removes the portion of the current continuation up to the nearest
prompt tagged by prompt-tag (not including the prompt; if no
such prompt exists, the exn:fail:contract:continuation exception is raised), or
up to the nearest continuation frame (if any) shared by the current
and captured continuations—whichever is first. While removing
continuation frames, dynamic-wind post-thunks are
executed. Finally, the (unshared portion of the) captured continuation
is appended to the remaining continuation, applying
dynamic-wind pre-thunks.
The arguments supplied to an applied procedure become the result
values for the restored continuation. In particular, if multiple
arguments are supplied, then the continuation receives multiple
results.
If, at application time, a continuation barrier would be
introduced by replacing the current continuation with the applied one,
then the exn:fail:contract:continuation exception is raised.
A continuation can be invoked from the thread (see
Threads) other than the one where it was captured.
Similar to
call-with-current-continuation, but applying
the resulting continuation procedure does not remove any portion of
the current continuation. Instead, application always extends the
current continuation with the captured continuation (without
installing any prompts other than those captured in the
continuation).
When call-with-composable-continuation is called, if a
continuation barrier appears in the continuation before the closest
prompt tagged by prompt-tag, the
exn:fail:contract:continuation exception is raised (because attempting to apply
the continuation would always fail).
Due to the limited applicability of its continuation,
call-with-escape-continuation can be implemented more efficiently
than call-with-current-continuation.
A continuation obtained from call-with-escape-continuation is
actually a kind of prompt. Escape continuations are provided mainly
for backwards compatibility, since they pre-date general prompts in
Racket, and because call/ec is often an easy replacement
for call/cc to improve performance.
Returns #t if cont, which must be a continuation,
includes a prompt tagged by prompt-tag, #f
otherwise.
Applies its three thunk arguments in order. The value of a
dynamic-wind expression is the value returned by
value-thunk. The
pre-thunk procedure is invoked
before calling
value-thunk and
post-thunk is invoked
after
value-thunk returns. The special properties of
dynamic-wind are manifest when control jumps into or out of
the
value-thunk application (either due to a prompt abort or
a continuation invocation): every time control jumps into the
value-thunk application,
pre-thunk is invoked, and
every time control jumps out of
value-thunk,
post-thunk is invoked. (No special handling is performed for
jumps into or out of the
pre-thunk and
post-thunk
applications.)
When dynamic-wind calls pre-thunk for normal
evaluation of value-thunk, the continuation of the
pre-thunk application calls value-thunk (with
dynamic-wind’s special jump handling) and then
post-thunk. Similarly, the continuation of the
post-thunk application returns the value of the preceding
value-thunk application to the continuation of the entire
dynamic-wind application.
When pre-thunk is called due to a continuation jump, the
continuation of pre-thunk
jumps to a more deeply nested pre-thunk, if any, or jumps
to the destination continuation; then
continues with the context of the pre-thunk’s
dynamic-wind call.
Normally, the second part of this continuation is never reached, due
to a jump in the first part. However, the second part is relevant
because it enables jumps to escape continuations that are contained in
the context of the dynamic-wind call. Furthermore, it means
that the continuation marks (see Continuation Marks) and
parameterization (see Parameters) for pre-thunk
correspond to those of the dynamic-wind call that installed
pre-thunk. The pre-thunk call, however, is
parameterize-breaked to disable breaks (see also
Breaks).
Similarly, when post-thunk is called due to a continuation
jump, the continuation of post-thunk jumps to a less deeply
nested post-thunk, if any, or jumps to a pre-thunk
protecting the destination, if any, or jumps to the destination
continuation, then continues from the post-thunk’s
dynamic-wind application. As for pre-thunk, the
parameterization of the original dynamic-wind call is
restored for the call, and the call is parameterize-breaked
to disable breaks.
In both cases, the target for a jump is recomputed after each
pre-thunk or post-thunk completes. When a
prompt-delimited continuation (see Prompts, Delimited Continuations, and Barriers) is
captured in a post-thunk, it might be delimited and
instantiated in such a way that the target of a jump turns out to be
different when the continuation is applied than when the continuation
was captured. There may even be no appropriate target, if a relevant
prompt or escape continuation is not in the continuation after the
restore; in that case, the first step in a pre-thunk or
post-thunk’s continuation can raise an exception.
Examples: |
| in pre out in post out | | 'cancel-canceled | | '((1 . 5) (2 . 6) (3 . 5) (1 . 5) (2 . 6) (3 . 5)) |
|
9.4.1 Classical Control Operators
The racket/control library provides various control operators
from the research literature on higher-order control operators, plus a
few extra convenience forms. These control operators are implemented
in terms of call-with-continuation-prompt,
call-with-composable-continuations, etc., and they generally
work sensibly together. Many are redundant; for example,
reset and prompt are aliases.
Returns the vs to a prompt using the default continuation
prompt tag and the default abort handler.
That is, (abort v ...) is equivalent to
(% expr) | (% expr handler-expr) |
|
|
Sitaram’s operators [Sitaram93].
The essential reduction rules are:
When handler-expr is omitted, % is the same as
prompt.
The essential reduction rules are:
Danvy and Filinski’s operators [
Danvy90].
The essential reduction rules are:
The reset and prompt forms are interchangeable.
|
(shift-at prompt-tag-expr identifer expr ...+) |
|
Like
reset and
shift, but using the specified prompt
tags.
The essential reduction rules are:
The reset0 and prompt0 forms are interchangeable.
Furthermore, the following reductions apply:
That is, both the prompt/reset and
control/shift sites must agree for 0-like
behavior, otherwise the non-0 behavior applies.
Variants of
prompt0, etc
., that accept a prompt tag.
The operators of Hieb and Dybvig [
Hieb90].
The essential reduction rules are:
The operator of Queinnec and Serpette [
Queinnec91].
The essential reduction rules are:
|
(set prompt-expr expr ...+) |
|
(cupto prompt-expr id expr ...+) |
|
The operators of Gunter et al. [
Gunter95].
In this library, new-prompt is an alias for
make-continuation-prompt-tag, set is an alias for
prompt0-at, and cupto is an alias for control0-at.