This section describes various primitive procedures which control the
flow of program execution in special ways. Procedures in this section
that invoke procedure arguments always do so in the same dynamic
environment as the call of the original procedure. The
procedure? predicate is also described here.
(procedure? obj) ¶Returns #t if obj is a procedure, otherwise returns
#f.
(procedure? car) ⇒ #t (procedure? 'car) ⇒ #f (procedure? (lambda (x) (* x x))) ⇒ #t (procedure? '(lambda (x) (* x x))) ⇒ #f (call-with-current-continuation procedure?) ⇒ #t
(apply proc arg1 … args) ¶The apply procedure calls proc with the elements of the
list (append (list arg1 …) args) as
the actual arguments.
(apply + (list 3 4)) ⇒ 7 (define compose (lambda (f g) (lambda args (f (apply g args))))) ((compose sqrt *) 12 75) ⇒ 30
(map proc list1 list2 …) ¶It is an error if proc does not accept as many arguments as there are lists and return a single value.
The map procedure applies proc element-wise to the elements
of the lists and returns a list of the results, in order. If more
than one list is given and not all lists have the same length,
map terminates when the shortest list runs out. The lists
can be circular, but it is an error if all of them are circular. It is
an error for proc to mutate any of the lists. The dynamic order
in which proc is applied to the elements of the
lists is unspecified. If multiple returns occur from
map, the values returned by earlier returns are not mutated.
(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 7)) ⇒ (5 7 9) (let ((count 0)) (map (lambda (ignored) (set! count (+ count 1)) count) '(a b))) ⇒ (1 2) or (2 1)
(string-map proc string1 string2 …) ¶It is an error if proc does not accept as many arguments as there are strings and return a single character.
The string-map procedure applies proc element-wise to the
elements of the strings and returns a string of the results, in
order. If more than one string is given and not all strings have
the same length, string-map terminates when the shortest string
runs out. The dynamic order in which proc is applied
to the elements of the strings is unspecified. If multiple
returns occur from string-map, the values returned by earlier
returns are not mutated.
(string-map char-foldcase "AbdEgH") ⇒ "abdegh" (string-map (lambda (c) (integer->char (+ 1 (char->integer c)))) "HAL") ⇒ "IBM" (string-map (lambda (c k) ((if (eqv? k #\u) char-upcase char-downcase) c)) "studlycaps xxx" "ululululul") ⇒ "StUdLyCaPs"
(vector-map proc vector1 vector2 …) ¶It is an error if proc does not accept as many arguments as there are vectors and return a single value.
The vector-map procedure applies proc element-wise to the
elements of the vectors and returns a vector of the results, in
order. If more than one vector is given and not all vectors have
the same length, vector-map terminates when the shortest vector
runs out. The dynamic order in which proc is applied
to the elements of the vectors is unspecified. If multiple
returns occur from vector-map, the values returned by earlier
returns are not mutated.
(vector-map cadr '#((a b) (d e) (g h))) ⇒ #(b e h) (vector-map (lambda (n) (expt n n)) '#(1 2 3 4 5)) ⇒ #(1 4 27 256 3125) (vector-map + '#(1 2 3) '#(4 5 6 7)) ⇒ #(5 7 9) (let ((count 0)) (vector-map (lambda (ignored) (set! count (+ count 1)) count) '#(a b))) ⇒ #(1 2) or #(2 1)
(for-each proc list1 list2 …) ¶It is an error if proc does not accept as many arguments as there are lists.
The arguments to for-each are like the arguments to map,
but for-each calls proc for its side effects rather than
for its values. Unlike map, for-each is guaranteed to
call proc on the elements of the lists in order
from the first element(s) to the last, and the value returned by
for-each is unspecified. If more than one list is given
and not all lists have the same length, for-each terminates when
the shortest list runs out. The lists can be circular, but it is
an error if all of them are circular.
It is an error for proc to mutate any of the lists.
(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)
(string-for-each proc string1 string2 …) ¶It is an error if proc does not accept as many arguments as there are strings.
The arguments to string-for-each are like the arguments to
string-map, but string-for-each calls proc for its side
effects rather than for its values. Unlike string-map,
string-for-each is guaranteed to call proc on the elements of
the strings in order from the first element(s) to the last, and
the value returned by string-for-each is unspecified. If more than
one string is given and not all strings have the same length,
string-for-each terminates when the shortest string runs out. It
is an error for proc to mutate any of the strings.
(let ((v '())) (string-for-each (lambda (c) (set! v (cons (char->integer c) v))) "abcde") v) ⇒ (101 100 99 98 97)
(vector-for-each proc vector1 vector2 …) ¶It is an error if proc does not accept as many arguments as there are vectors.
The arguments to vector-for-each are like the arguments to
vector-map, but vector-for-each calls proc for its side
effects rather than for its values. Unlike vector-map,
vector-for-each is guaranteed to call proc on the elements of
the vectors in order from the first element(s) to the last, and
the value returned by vector-for-each is unspecified. If more than
one vector is given and not all vectors have the same length,
vector-for-each terminates when the shortest vector runs out. It
is an error for proc to mutate any of the vectors.
(let ((v (make-list 5))) (vector-for-each (lambda (i) (list-set! v i (* i i))) '#(0 1 2 3 4)) v) ⇒ (0 1 4 9 16)
(call-with-current-continuation proc) ¶(call/cc proc) ¶It is an error if proc does not accept one argument.
The procedure call-with-current-continuation (or its equivalent
abbreviation call/cc) packages the current continuation (see the
rationale below) as an “escape procedure” and passes it as an
argument to proc. 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 will cause the invocation of before and after
thunks installed using dynamic-wind.
The escape procedure accepts the same number of arguments as the
continuation to the original call to
call-with-current-continuation. Most continuations take only one
value. Continuations created by the call-with-values procedure
(including the initialization expressions of define-values,
let-values, and let*-values expressions), take the number of
values that the consumer expects. The continuations of all non-final
expressions within a sequence of expressions, such as in lambda,
case-lambda, begin, let, let*, letrec,
letrec*, let-values, let*-values, let-syntax,
letrec-syntax, parameterize, guard, case, cond,
when, and unless expressions, take an arbitrary number of
values because they discard the values passed to them in any event. The
effect of passing no values or more than one value to continuations that
were not created in one of these ways is unspecified.
The escape procedure that is passed to proc has unlimited extent
just like any other procedure in Scheme. It can be stored in variables
or data structures and can be called as many times as desired. However,
like the raise and error procedures, it never returns to
its caller.
The following examples show only the simplest ways in which
call-with-current-continuation is used. If all real uses 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
Rationale: A common use of
call-with-current-continuationis for structured, non-local exits from loops or procedure bodies, but in factcall-with-current-continuationis useful for implementing a wide variety of advanced control structures. In fact,raiseandguardprovide a more structured mechanism for non-local exits.Whenever a Scheme expression is evaluated there is a continuation wanting the result of the expression. The continuation represents an entire (default) future for the computation. If the expression is evaluated at the REPL, 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 REPL’s 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 needs to deal with continuations explicitly. The
call-with-current-continuationprocedure allows Scheme programmers to do that by creating a procedure that acts just like the current continuation.
(values obj …) ¶Delivers all of its arguments to its continuation. The values
procedure might be defined as follows:
(define (values . things) (call-with-current-continuation (lambda (cont) (apply cont things))))
(call-with-values producer consumer) ¶Calls its producer argument with no arguments and a continuation
that, when passed some values, calls the consumer procedure with
those values as arguments. The continuation for the call to
consumer is the continuation of the call to
call-with-values.
(call-with-values (lambda () (values 4 5)) (lambda (a b) b)) ⇒ 5 (call-with-values * -) ⇒ -1
(dynamic-wind before thunk after) ¶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. The before and
after thunks are called in the same dynamic environment as the
call to dynamic-wind. In Scheme, because of
call-with-current-continuation, the dynamic extent of a call is
not always 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 unspecified.
(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)