Next: Application Hooks, Previous: Primitive Procedures, Up: Procedures [Contents][Index]
Procedure must be a procedure of one argument. Packages up the
current continuation (see below) as an escape procedure and passes
it as an argument to procedure. The escape procedure is a Scheme
procedure of one argument that, if it is later passed a value, will
ignore whatever continuation is in effect at that later time and will
give the value instead to the continuation that was in effect when the
escape procedure was created. The escape procedure created by
call-with-current-continuation
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.
The following examples show only the most common uses of this procedure.
If all real programs were as simple as these examples, there would be no
need for a procedure with the power of
call-with-current-continuation
.
(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
A common use of call-with-current-continuation
is for structured,
non-local exits from loops or procedure bodies, but in fact
call-with-current-continuation
is quite useful for implementing a
wide variety of advanced control structures.
Whenever a Scheme expression is evaluated a continuation exists that
wants the result of the expression. The continuation represents an
entire (default) future for the computation. If the expression is
evaluated at top level, for example, the continuation will 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
don’t think much about them. On the rare occasions that you may need to
deal explicitly with continuations,
call-with-current-continuation
lets you do so by creating a
procedure that acts just like the current continuation.
Returns #t
if object is a continuation; otherwise returns
#f
.
Thunk must be a procedure of no arguments. Conceptually,
within-continuation
invokes continuation on the result of
invoking thunk, but thunk is executed in the dynamic state
of continuation. In other words, the “current” continuation is
abandoned before thunk is invoked.
Calls thunk without arguments, returning the result(s) of this
call. Before and after are called, also without arguments,
as required by the following rules. Note that in the absence of calls to
continuations captured using call-with-current-continuation
the
three arguments are called once each, in order. Before is called
whenever execution enters the dynamic extent of the call to thunk
and after 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
call-with-current-continuation
, the dynamic extent of a call may
not be a single, connected time period. It is defined as follows:
call-with-current-continuation
) during the dynamic extent.
If a second call to dynamic-wind
occurs within the dynamic extent
of the call to thunk and then a continuation is invoked in such a
way that the afters from these two invocations of
dynamic-wind
are both to be called, then the after
associated with the second (inner) call to dynamic-wind
is called
first.
If a second call to dynamic-wind
occurs within the dynamic extent
of the call to thunk and then a continuation is invoked in such a
way that the befores from these two invocations of
dynamic-wind
are both to be called, then the before
associated with the first (outer) call to dynamic-wind
is called
first.
If invoking a continuation requires calling the before from one
call to dynamic-wind
and the after from another, then the
after is called first.
The effect of using a captured continuation to enter or exit the dynamic extent of a call to before or after is undefined.
(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)
The following two procedures support multiple values.
Thunk must be a procedure of no arguments, and procedure
must be a procedure. Thunk is invoked with a continuation that
expects to receive multiple values; specifically, the continuation
expects to receive the same number of values that procedure
accepts as arguments. Thunk must return multiple values using the
values
procedure. Then procedure is called with the
multiple values as its arguments. The result yielded by procedure
is returned as the result of call-with-values
.
Returns multiple values. The continuation in effect when this procedure
is called must be a multiple-value continuation that was created by
call-with-values
. Furthermore it must accept as many values as
there are objects.
Next: Application Hooks, Previous: Primitive Procedures, Up: Procedures [Contents][Index]