2.18 Iterations and Comprehensions: for, for/list, ...
 Iterations and Comprehensions in Guide: Racket introduces iterations and comprehensions.
Iterations and Comprehensions in Guide: Racket introduces iterations and comprehensions.
The for iteration forms are based on SRFI-42
[SRFI-42].
2.18.1 Iteration and Comprehension Forms
| (for (for-clause ...) body ...+) | 
|  | 
| | for-clause |  | = |  | [id seq-expr] |  |  |  | | |  | [(id ...) seq-expr] |  |  |  | | |  | #:when guard-expr | 
 | 
|  | 
|  | 
Iteratively evaluates body. The for-clauses
introduce bindings whose scope includes body and that
determine the number of times that body is evaluated.
In the simple case, each for-clause has one of its first two
forms, where [id seq-expr] is a shorthand for [(id) seq-expr].  In this simple case, the seq-exprs are evaluated
left-to-right, and each must produce a sequence value (see
Sequences).
The for form iterates by drawing an element from each
sequence; if any sequence is empty, then the iteration stops, and
#<void> is the result of the for expression. Otherwise
a location is created for each id to hold the values of each
element; the sequence produced by a seq-expr must return as
many values for each iteration as corresponding ids.
The ids are then bound in the body, which is
evaluated, and whose results are ignored. Iteration continues with the
next element in each sequence and with fresh locations for each
id.
A for form with zero for-clauses is equivalent to a
single for-clause that binds an unreferenced id to
a sequence containing a single element. All of the ids must
be distinct according to bound-identifier=?.
If any for-clause has the form #:when guard-expr,
then only the preceding clauses (containing no #:when)
determine iteration as above, and the body is effectively
wrapped as
| (when guard-expr | 
| (for (for-clause ...) body ...+)) | 
using the remaining for-clauses.
| Examples: | 
|  | 
|   (1 a #t)(1 a #f)(3 c #t)(3 c #f) | 
|  | 
|   (a 1)(b 20) | 
|  | 
|   here | 
| | > (for ([i '()]) |  | (error "doesn't get here")) | 
 | 
 Iterates like
for, but that the last expression in the 
bodys must
produce a single value, and the result of the 
for/list
expression is a list of the results in order.
| Examples: | 
|  | 
|   '((1 #\a #t) (1 #\a #f) (3 #\c #t) (3 #\c #f)) | 
| > (for/list () 'any) | 
|   '(any) | 
|  | 
|   '() | 
Like 
for/list, but the result is an immutable 
hash
table; 
for/hash creates a table using 
equal? to
distinguish keys, 
for/hasheq produces a table using
eq?, and 
for/hasheqv produces a table using
eqv?. The last expression in the 
bodys must return
two values: a key and a value to extend the hash table accumulated by
the iteration.
| Example: | 
|  | 
|   '#hash((1 . "1") (2 . "2") (3 . "3")) | 
| (for/and (for-clause ...) body ...+) | 
 Iterates like
for, but when last expression of 
body produces
#f, then iteration terminates, and the result of the
for/and expression is 
#f. If the 
body
is never evaluated, then the result of the 
for/and
expression is 
#t. Otherwise, the result is the (single)
result from the last evaluation of 
body.
| Examples: | 
| | > (for/and ([i '(1 2 3 "x")]) |  | (i . < . 3)) | 
 | 
|   #f | 
|  | 
|   4 | 
|  | 
|   #t | 
| (for/or (for-clause ...) body ...+) | 
 Iterates like
for, but when last expression of 
body produces
a value other than 
#f, then iteration terminates, and
the result of the 
for/or expression is the same
(single) value. If the 
body is never evaluated, then the
result of the 
for/or expression is
#f. Otherwise, the result is 
#f.
| Examples: | 
| | > (for/or ([i '(1 2 3 "x")]) |  | (i . < . 3)) | 
 | 
|   #t | 
|  | 
|   1 | 
|  | 
|   #f | 
| (for/lists (id ...) (for-clause ...) body ...+) | 
Similar to 
for/list, but the last 
body expression
should produce as many values as given 
ids, and the result is
as many lists as supplied 
ids. The 
ids are bound to
the lists accumulated so far in the 
for-clauses and
bodys.
 Iterates like
for, but after 
body is evaluated the first
time, then the iteration terminates, and the 
for/first
result is the (single) result of 
body. If the
body is never evaluated, then the result of the
for/first expression is 
#f.
 Iterates like
for, but the 
for/last result is the (single)
result of of the last evaluation of 
body. If the
body is never evaluated, then the result of the
for/last expression is 
#f.
| (for/fold ([accum-id init-expr] ...) (for-clause ...) . body) | 
Iterates like 
for. Before iteration starts, the
init-exprs are evaluated to produce initial accumulator
values. At the start of each iteration, a location is generated
for each 
accum-id, and the corresponding current accumulator
value is placed into the location. The last expression in
body must produce as many values as 
accum-ids, and
those values become the current accumulator values. When iteration
terminates, the results of the 
fold/for expression are the
accumulator values.
| Example: | 
|  | 
|   10 | 
|   '(2 1.7320508075688772 1.4142135623730951 1) | 
| (for* (for-clause ...) body ...+) | 
Like 
for, but with an implicit 
#:when #t between
each pair of 
for-clauses, so that all sequence iterations are
nested.
| Example: | 
|  | 
|   (1 a)(1 b)(2 a)(2 b) | 
|  | 
|  | 
|  | 
|  | 
|  | 
|  | 
| | (for*/or (for-clause ...) body ...+) | 
 | 
|  | 
|  | 
| | (for*/fold ([accum-id init-expr] ...) (for-clause ...) body ...+) | 
 | 
| Example: | 
|  | 
|   '((1 #\a) (1 #\b) (2 #\a) (2 #\b)) | 
2.18.2 Deriving New Iteration Forms
| | (for/fold/derived orig-datum |  | ([accum-id init-expr] ...) (for-clause ...) body ...+) | 
 | 
Like 
for/fold, but the extra 
orig-datum is used as the source for all syntax errors.
Like 
for*/fold, but the extra 
orig-datum is used as the source for all syntax errors.
Defines 
id as syntax. An 
(id . rest) form is
treated specially when used to generate a sequence in a
clause of 
for (or one of its variants). In that
case, the procedure result of 
clause-transform-expr is called
to transform the clause.
When id is used in any other expression position, the result
of expr-transform-expr is used. If it is a procedure of zero
arguments, then the result must be an identifier other-id,
and any use of id is converted to a use of
other-id. Otherwise,expr-transform-expr must
produce a procedure (of one argument) that is used as a macro
transformer.
When the clause-transform-expr transformer is used, it is
given a clause as an argument, where the clause’s form is
normalized so that the left-hand side is a parenthesized sequence of
identifiers. The right-hand side is of the form (id . rest).
The result can be either #f, to indicate that the forms
should not be treated specially (perhaps because the number of bound
identifiers is inconsistent with the (id . rest) form), or a
new clause to to replace the given one. The new clause might
use :do-in.
| | (:do-in ([(outer-id ...) outer-expr] ...) |  | outer-check |  | ([loop-id loop-expr] ...) |  | pos-guard |  | ([(inner-id ...) inner-expr] ...) |  | pre-guard |  | post-guard |  | (loop-arg ...)) | 
 | 
A form that can only be used as a 
seq-expr in a
clause of 
for (or one of its variants).
Within a for, the pieces of the :do-in form are
spliced into the iteration essentially as follows:
| (let-values ([(outer-id ...) outer-expr] ...) | 
| outer-check | 
| (let loop ([loop-id loop-expr] ...) | 
| (if pos-guard | 
| (let-values ([(inner-id ...) inner-expr] ...) | 
| (if pre-guard | 
| (let body-bindings | 
| (if post-guard | 
| (loop loop-arg ...) | 
| done-expr)) | 
| done-expr)) | 
| done-expr))) | 
where body-bindings and done-expr are from the
context of the :do-in use. The identifiers bound by the
for clause are typically part of the ([(inner-id ...) inner-expr] ...) section.
The actual loop binding and call has additional loop
arguments to support iterations in parallel with the :do-in
form, and the other pieces are similarly accompanied by pieces from
parallel iterations.
2.18.3 Do Loops
| | (do ([id init-expr step-expr-maybe] ...) |  | (stop?-expr finish-expr ...) |  | expr ...+) | 
 | 
|  | 
| | step-expr-maybe |  | = |  |  |  |  |  | | |  | step-expr | 
 | 
Iteratively evaluates the exprs for as long as
stop?-expr returns #f.
To initialize the loop, the init-exprs are evaluated in order
and bound to the corresponding ids. The ids are
bound in all expressions within the form other than the
init-exprs.
After the ids are bound, then stop?-expr is
evaluated. If it produces #f, each expr is evaluated
for its side-effect. The ids are then effectively updated
with the values of the step-exprs, where the default
step-expr for id is just id; more
precisely, iteration continues with fresh locations for the
ids that are initialized with the values of the corresponding
step-exprs.
When stop?-expr produces a true value, then the
finish-exprs are evaluated in order, and the last one is
evaluated in tail position to produce the overall value for the
do form. If no finish-expr is provided, the value of
the do form is #<void>.