r7rs-small-texinfo

Unnamed repository; edit this file 'description' to name the repository.
git clone https://kaka.farm/~git/r7rs-small-texinfo
Log | Files | Refs | README | LICENSE

control-features.texinfo (15431B)


      1 @node Control features
      2 @section Control features
      3 
      4 This section describes various primitive procedures which control
      5 the flow of program execution in special ways. Procedures in this
      6 section that invoke procedure arguments always do so in the same
      7 dynamic environment as the call of the original procedure. The
      8 @code{procedure?} predicate is also described here.
      9 
     10 @deffn procedure procedure? obj
     11 
     12 Returns @code{#t} if
     13 @var{obj} is a procedure, otherwise returns @code{#f}.
     14 
     15 @lisp
     16 (procedure? car)       @result{} #t
     17 (procedure? 'car)      @result{} #f
     18 (procedure? (lambda (x) (* x x)))
     19                        @result{} #t
     20 (procedure? '(lambda (x) (* x x)))
     21                        @result{} #f
     22 (call-with-current-continuation procedure?)
     23                        @result{} #t
     24 @end lisp
     25 
     26 @end deffn
     27 
     28 @deffn procedure apply proc @vari{arg}@dots{} args
     29 
     30 The @code{apply} procedure calls @var{proc} with the elements of the
     31 list @code{(append (list }@vari{arg} @dots{}@code{) args)} as the
     32 actual arguments.
     33 
     34 @lisp
     35 (apply + (list 3 4)) @result{} 7
     36 
     37 (define compose
     38   (lambda (f g)
     39     (lambda args
     40       (f (apply g args)))))
     41 
     42 ((compose sqrt *) 12 75) @result{} 30
     43 @end lisp
     44 
     45 @end deffn
     46 
     47 @deffn procedure map proc @vari{list} @varii{list}@dots{}
     48 
     49 It is an error if @var{proc} does not accept as many arguments as
     50 there are @var{list}s and return a single value.
     51 
     52 The @code{map} procedure applies @var{proc} element-wise to the
     53 elements of the @var{list}s and returns a list of the results, in
     54 order.  If more than one @var{list} is given and not all lists have
     55 the same length, @code{map} terminates when the shortest list runs out.
     56 The @var{list}s can be circular, but it is an error if all of them are
     57 circular.  It is an error for @var{proc} to mutate any of the lists.
     58 The dynamic order in which @var{proc} is applied to the elements
     59 of the @var{list}s is unspecified.  If multiple returns occur from
     60 @code{map}, the values returned by earlier returns are not mutated.
     61 
     62 @lisp
     63 (map cadr '((a b) (d e) (g h))) @result{} (b e h)
     64 
     65 (map (lambda (n) (expt n n))
     66      '(1 2 3 4 5))
     67     @result{} (1 4 27 256 3125)
     68 
     69 (map + '(1 2 3) '(4 5 6 7)) @result{} (5 7 9)
     70 
     71 (let ((count 0))
     72   (map (lambda (ignored)
     73          (set! count (+ count 1))
     74          count)
     75        '(a b)))
     76     @result{} (1 2) @r{or} (2 1)
     77 @end lisp
     78 
     79 @end deffn
     80 
     81 @deffn procedure string-map proc @vari{string} @varii{string}@dots{}
     82 
     83 It is an error if @var{proc} does not accept as many arguments as
     84 there are @var{string}s and return a single character.
     85 
     86 The @code{string-map} procedure applies @var{proc} element-wise to
     87 the elements of the @var{string}s and returns a string of the results,
     88 in order.  If more than one @var{string} is given and not all strings
     89 have the same length, @code{string-map} terminates when the shortest
     90 string runs out.  The dynamic order in which @var{proc} is applied
     91 to the elements of the @var{string}s is unspecified.  If multiple
     92 returns occur from @code{string-map}, the values returned by earlier
     93 returns are not mutated.
     94 
     95 @lisp
     96 (string-map char-foldcase "AbdEgH") @result{} "abdegh"
     97 
     98 (string-map
     99  (lambda (c)
    100    (integer->char (+ 1 (char->integer c))))
    101  "HAL")
    102     @result{} "IBM"
    103 
    104 (string-map
    105  (lambda (c k)
    106    ((if (eqv? k #\u) char-upcase char-downcase)
    107     c))
    108  "studlycaps xxx"
    109  "ululululul")
    110     @result{} "StUdLyCaPs"
    111 @end lisp
    112 
    113 @end deffn
    114 
    115 @deffn procedure vector-map proc @vari{vector} @varii{vector}@dots{}
    116 
    117 It is an error if @var{proc} does not accept as many arguments as
    118 there are @var{vector}s and return a single value.
    119 
    120 The @code{vector-map} procedure applies @var{proc} element-wise to
    121 the elements of the @var{vector}s and returns a vector of the results,
    122 in order.  If more than one @var{vector} is given and not all vectors
    123 have the same length, @code{vector-map} terminates when the shortest
    124 vector runs out.  The dynamic order in which @var{proc} is applied
    125 to the elements of the @var{vector}s is unspecified.  If multiple
    126 returns occur from @code{vector-map}, the values returned by earlier
    127 returns are not mutated.
    128 
    129 @lisp
    130 (vector-map cadr '#((a b) (d e) (g h))) @result{} #(b e h)
    131 
    132 (vector-map (lambda (n) (expt n n))
    133             '#(1 2 3 4 5))
    134     @result{} #(1 4 27 256 3125)
    135 
    136 (vector-map + '#(1 2 3) '#(4 5 6 7)) @result{} #(5 7 9)
    137 
    138 (let ((count 0))
    139   (vector-map
    140    (lambda (ignored)
    141      (set! count (+ count 1))
    142      count)
    143    '#(a b)))
    144     @result{} #(1 2) @r{or} #(2 1)
    145 @end lisp
    146 
    147 @end deffn
    148 
    149 @deffn procedure for-each proc @vari{list} @varii{list}@dots{}
    150 
    151 It is an error if @var{proc} does not accept as many arguments as
    152 there are @var{list}s.
    153 
    154 The arguments to @code{for-each} are like the arguments to @code{map},
    155 but @code{for-each} calls @var{proc} for its side effects rather than
    156 for its values.  Unlike @code{map}, @code{for-each} is guaranteed
    157 to call @var{proc} on the elements of the @var{list}s in order
    158 from the first element(s) to the last, and the value returned by
    159 @code{for-each} is unspecified.  If more than one @var{list} is given
    160 and not all lists have the same length, @code{for-each} terminates
    161 when the shortest list runs out.  The @var{list}s can be circular,
    162 but it is an error if all of them are circular.
    163 
    164 It is an error for @var{proc} to mutate any of the lists.
    165 
    166 @lisp
    167 (let ((v (make-vector 5)))
    168   (for-each (lambda (i)
    169               (vector-set! v i (* i i)))
    170             '(0 1 2 3 4))
    171   v)
    172     @result{} #(0 1 4 9 16)
    173 @end lisp
    174 @end deffn
    175 
    176 @deffn procedure string-for-each proc string1 string2@dots{}
    177 
    178 It is an error if @var{proc} does not accept as many arguments as
    179 there are @var{string}s.
    180 
    181 The arguments to @code{string-for-each} are like the arguments to
    182 @code{string-map}, but @code{string-for-each} calls @var{proc} for its
    183 side effects rather than for its values.  Unlike @code{string-map},
    184 @code{string-for-each} is guaranteed to call @var{proc} on the elements
    185 of the @var{string}s in order from the first element(s) to the last,
    186 and the value returned by @code{string-for-each} is unspecified.
    187 If more than one @var{string} is given and not all strings have the
    188 same length, @code{string-for-each} terminates when the shortest string
    189 runs out.  It is an error for @var{proc} to mutate any of the strings.
    190 
    191 @lisp
    192 (let ((v '()))
    193   (string-for-each
    194    (lambda (c) (set! v (cons (char->integer c) v)))
    195    "abcde")
    196   v)
    197     @result{} (101 100 99 98 97)
    198 @end lisp
    199 
    200 @end deffn
    201 
    202 @deffn procedure vector-for-each proc @vari{vector} @varii{vector}@dots{}
    203 
    204 It is an error if @var{proc} does not accept as many arguments as
    205 there are @var{vector}s.
    206 
    207 The arguments to @code{vector-for-each} are like the arguments to
    208 @code{vector-map}, but @code{vector-for-each} calls @var{proc} for its
    209 side effects rather than for its values.  Unlike @code{vector-map},
    210 @code{vector-for-each} is guaranteed to call @var{proc} on the elements
    211 of the @var{vector}s in order from the first element(s) to the last,
    212 and the value returned by @code{vector-for-each} is unspecified.
    213 If more than one @var{vector} is given and not all vectors have the
    214 same length, @code{vector-for-each} terminates when the shortest vector
    215 runs out.  It is an error for @var{proc} to mutate any of the vectors.
    216 
    217 @lisp
    218 (let ((v (make-list 5)))
    219   (vector-for-each
    220    (lambda (i) (list-set! v i (* i i)))
    221    '#(0 1 2 3 4))
    222   v)
    223     @result{} (0 1 4 9 16)
    224 @end lisp
    225 
    226 @end deffn
    227 
    228 @deffn  procedure call-with-current-continuation proc
    229 @deffnx procedure call/cc proc
    230 
    231 It is an error if @var{proc} does not accept one
    232 argument.
    233 
    234 @cindex escape procedure
    235 
    236 The procedure @code{call-with-current-continuation} (or its equivalent
    237 abbreviation @code{call/cc}) packages the current continuation (see
    238 the rationale below) as an ``escape procedure'' and passes it as an
    239 argument to @var{proc}.  The escape procedure is a Scheme procedure
    240 that, if it is later called, will abandon whatever continuation is in
    241 effect at that later time and will instead use the continuation that
    242 was in effect when the escape procedure was created.  Calling the
    243 escape procedure will cause the invocation of @var{before} and
    244 @var{after} thunks installed using @code{dynamic-wind}.
    245 
    246 The escape procedure accepts the same number of
    247 arguments as the continuation to the original call to
    248 @code{call-with-current-continuation}.  Most continuations take only
    249 one value.  Continuations created by the @code{call-with-values}
    250 procedure (including the initialization expressions of
    251 @code{define-values}, @code{let-values}, and @code{let*-values}
    252 expressions), take the number of values that the consumer expects.
    253 The continuations of all non-final expressions within a sequence
    254 of expressions, such as in @code{lambda}, @code{case-lambda},
    255 @code{begin}, @code{let}, @code{let*}, @code{letrec}, @code{letrec*},
    256 @code{let-values}, @code{let*-values}, @code{let-syntax},
    257 @code{letrec-syntax}, @code{parameterize}, @code{guard}, @code{case},
    258 @code{cond}, @code{when}, and @code{unless} expressions, take an
    259 arbitrary number of values because they discard the values passed to
    260 them in any event.  The effect of passing no values or more than one
    261 value to continuations that were not created in one of these ways
    262 is unspecified.
    263 
    264 The escape procedure that is passed to @var{proc} has unlimited
    265 extent just like any other procedure in Scheme.  It can be stored
    266 in variables or data structures and can be called as many times as
    267 desired.  However, like the @code{raise} and @code{error} procedures,
    268 it never returns to its caller.
    269 
    270 The following examples show only the simplest ways in which
    271 @code{call-with-current-continuation} is used.  If all real uses were
    272 as simple as these examples, there would be no need for a procedure
    273 with the power of @code{call-with-current-continuation}.
    274 
    275 @lisp
    276 (call-with-current-continuation
    277   (lambda (exit)
    278     (for-each (lambda (x)
    279                 (if (negative? x)
    280                     (exit x)))
    281               '(54 0 37 -3 245 19))
    282     #t))
    283     @result{} -3
    284 
    285 (define list-length
    286   (lambda (obj)
    287     (call-with-current-continuation
    288       (lambda (return)
    289         (letrec ((r
    290                   (lambda (obj)
    291                     (cond ((null? obj) 0)
    292                           ((pair? obj)
    293                            (+ (r (cdr obj)) 1))
    294                           (else (return #f))))))
    295           (r obj))))))
    296 
    297 (list-length '(1 2 3 4)) @result{} 4
    298 
    299 (list-length '(a b . c)) @result{} #f
    300 @end lisp
    301 
    302 @rationale{}
    303 
    304 A common use of @code{call-with-current-continuation} is for
    305 structured, non-local exits from loops or procedure bodies, but in
    306 fact @code{call-with-current-continuation} is useful for implementing a
    307 wide variety of advanced control structures.  In fact, @code{raise} and
    308 @code{guard} provide a more structured mechanism for non-local exits.
    309 
    310 Whenever a Scheme expression is evaluated there is a @define{continuation}
    311 wanting the result of the expression.  The continuation represents
    312 an entire (default) future for the computation.  If the expression is
    313 evaluated at the REPL, for example, then the continuation might take
    314 the result, print it on the screen, prompt for the next input, evaluate
    315 it, and so on forever.  Most of the time the continuation includes
    316 actions specified by user code, as in a continuation that will take
    317 the result, multiply it by the value stored in a local variable, add
    318 seven, and give the answer to the REPL's continuation to be printed.
    319 Normally these ubiquitous continuations are hidden behind the scenes
    320 and programmers do not think much about them.  On rare occasions,
    321 however, a programmer needs to deal with continuations explicitly.
    322 The @code{call-with-current-continuation} procedure allows Scheme
    323 programmers to do that by creating a procedure that acts just like
    324 the current continuation.
    325 
    326 @end deffn
    327 
    328 @deffn procedure values obj@dots{}
    329 
    330 Delivers all of its arguments to its continuation. The @code{values}
    331 procedure might be defined as follows:
    332 
    333 @lisp
    334 (define (values . things)
    335   (call-with-current-continuation
    336     (lambda (cont) (apply cont things))))
    337 @end lisp
    338 
    339 @end deffn
    340 
    341 @deffn procedure call-with-values producer consumer
    342 
    343 Calls its @var{producer} argument with no arguments and a continuation
    344 that, when passed some values, calls the @var{consumer} procedure with
    345 those values as arguments. The continuation for the call to
    346 @var{consumer} is the continuation of the call to
    347 @code{call-with-values}.
    348 
    349 @lisp
    350 (call-with-values (lambda () (values 4 5))
    351                   (lambda (a b) b))
    352     @result{} 5
    353 
    354 (call-with-values * -) @result{} -1
    355 @end lisp
    356 @end deffn
    357 
    358 @deffn procedure dynamic-wind before thunk after
    359 
    360 Calls @var{thunk} without arguments, returning the result(s) of this
    361 call.  @var{Before} and @var{after} are called, also without arguments,
    362 as required by the following rules.  Note that, in the absence of calls
    363 to continuations captured using @code{call-with-current-continuation},
    364 the three arguments are called once each, in order.  @var{Before}
    365 is called whenever execution enters the dynamic extent of the
    366 call to @var{thunk} and @var{after} is called whenever it exits
    367 that dynamic extent.  The dynamic extent of a procedure call is
    368 the period between when the call is initiated and when it returns.
    369 The @var{before} and @var{after} thunks are called in the same dynamic
    370 environment as the call to @code{dynamic-wind}.  In Scheme, because of
    371 @code{call-with-current-continuation}, the dynamic extent of a call is
    372 not always a single, connected time period.  It is defined as follows:
    373 
    374 @itemize @bullet
    375 
    376 @item
    377 The dynamic extent is entered when execution of the body of the
    378 called procedure begins.
    379 
    380 @item
    381 The dynamic extent is also entered when execution is not within
    382 the dynamic extent and a continuation is invoked that was captured
    383 (using @code{call-with-current-continuation}) during the dynamic
    384 extent.
    385 
    386 @item
    387 It is exited when the called procedure returns.
    388 
    389 @item
    390 It is also exited when execution is within the dynamic extent and a
    391 continuation is invoked that was captured while not within the dynamic
    392 extent.
    393 
    394 @end itemize
    395 
    396 If a second call to @code{dynamic-wind} occurs within the dynamic
    397 extent of the call to @var{thunk} and then a continuation is invoked
    398 in such a way that the @var{after}s from these two invocations of
    399 @code{dynamic-wind} are both to be called, then the @var{after}
    400 associated with the second (inner) call to @code{dynamic-wind} is
    401 called first.
    402 
    403 If a second call to @code{dynamic-wind} occurs within the dynamic
    404 extent of the call to @var{thunk} and then a continuation is invoked
    405 in such a way that the @var{before}s from these two invocations of
    406 @code{dynamic-wind} are both to be called, then the @var{before}
    407 associated with the first (outer) call to @code{dynamic-wind} is
    408 called first.
    409 
    410 If invoking a continuation requires calling the @var{before} from
    411 one call to @code{dynamic-wind} and the @var{after} from another,
    412 then the @var{after} is called first.
    413 
    414 The effect of using a captured continuation to enter or exit the
    415 dynamic extent of a call to @var{before} or @var{after} is unspecified.
    416 
    417 @lisp
    418 (let ((path '())
    419       (c #f))
    420   (let ((add (lambda (s)
    421                (set! path (cons s path)))))
    422     (dynamic-wind
    423       (lambda () (add 'connect))
    424       (lambda ()
    425         (add (call-with-current-continuation
    426                (lambda (c0)
    427                  (set! c c0)
    428                  'talk1))))
    429       (lambda () (add 'disconnect)))
    430     (if (< (length path) 4)
    431         (c 'talk2)
    432         (reverse path))))
    433 
    434     @result{} (connect talk1 disconnect
    435                connect talk2 disconnect)
    436 @end lisp
    437 
    438 @end deffn