3.18 Iterations and Comprehensions: for, for/list, ...

► |  | The Racket Reference

1 | Language Model
2 | Notation for Documentation
3 | Syntactic Forms
4 | Datatypes
5 | Structures
6 | Classes and Objects
7 | Units
8 | Contracts
9 | Pattern Matching
10 | Control Flow
11 | Concurrency and Parallelism
12 | Macros
13 | Input and Output
14 | Reflection and Security
15 | Operating System
16 | Memory Management
17 | Unsafe Operations
18 | Running Racket
| Bibliography
| Index

▼ | 3 | Syntactic Forms

3.1 | Modules: module, module*, ...
3.2 | Importing and Exporting: require and provide
3.3 | Literals: quote and #%datum
3.4 | Expression Wrapper: #%expression
3.5 | Variable References and #%top
3.6 | Locations: #%variable-reference
3.7 | Procedure Applications and #%app
3.8 | Procedure Expressions: lambda and case-lambda
3.9 | Local Binding: let, let*, letrec, ...
3.10 | Local Definitions: local
3.11 | Constructing Graphs: shared
3.12 | Conditionals: if, cond, and, and or
3.13 | Dispatch: case
3.14 | Definitions: define, define-syntax, ...
3.15 | Sequencing: begin, begin0, and begin-for-syntax
3.16 | Guarded Evaluation: when and unless
3.17 | Assignment: set! and set!-values
3.18 | Iterations and Comprehensions: for, for/ list, ...
3.19 | Continuation Marks: with-continuation-mark
3.20 | Quasiquoting: quasiquote, unquote, and unquote-splicing
3.21 | Syntax Quoting: quote-syntax
3.22 | Interaction Wrapper: #%top-interaction
3.23 | Blocks: block
3.24 | Internal-Definition Limiting: #%stratified-body
3.25 | Performance Hints: begin-encourage-inline
3.26 | Importing Modules Lazily: lazy-require

► | 3.18 | Iterations and Comprehensions: for, for/ list, ...

3.18.1 | Iteration and Comprehension Forms
3.18.2 | Deriving New Iteration Forms
3.18.3 | Do Loops

On this page:

3.18.1`` Iteration and Comprehension Forms
for
for/ list
for/ vector
for/ hash
for/ hasheq
for/ hasheqv
for/ and
for/ or
for/ sum
for/ product
for/ lists
for/ first
for/ last
for/ fold
for*
for*/ list
for*/ lists
for*/ vector
for*/ hash
for*/ hasheq
for*/ hasheqv
for*/ and
for*/ or
for*/ sum
for*/ product
for*/ first
for*/ last
for*/ fold
3.18.2`` Deriving New Iteration Forms
for/ fold/ derived
for*/ fold/ derived
define-sequence-syntax
: do-in
for-clause-syntax-protect
3.18.3`` Do Loops
do

top ← prev up next →

#### 3.18`` Iterations and Comprehensions: for, for/list, ...

> > > Iterations and Comprehensions in The Racket Guide introduces iterations and comprehensions.

The for iteration forms are based on SRFI-42 [SRFI-42].

##### 3.18.1`` Iteration and Comprehension Forms

> syntax (for (for-clause ...) body-or-break ... body)
> for-clause |  | = |  | [id seq-expr]
> |  | | |  | [(id ...) seq-expr]
> |  | | |  | #:when guard-expr
> |  | | |  | #:unless guard-expr
> |  | | |  | break-clause
> break-clause |  | = |  | #:break guard-expr
> |  | | |  | #:final guard-expr
> body-or-break |  | = |  | body
> |  | | |  | break-clause
> | seq-expr |  | : |  | sequence?

Iteratively evaluates bodys. The for-clauses introduce bindings whose scope includes body and that determine the number of times that body is evaluated. A break-clause either among the for-clauses or bodys stops further iteration.

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 or #:unless) determine iteration as above, and the body is effectively wrapped as

> (when guard-expr
> (for (for-clause ...) body ...+))

using the remaining for-clauses. A for-clause of the form #:unless guard-expr corresponds to the same transformation with unless in place of when.

A #:break guard-expr clause is similar to a #:unless guard-expr clause, but when #:break avoids evaluation of the bodys, it also effectively ends all sequences within the for form. A #:final guard-expr clause is similar to #:break guard-expr, but instead of immediately ending sequences and skipping the bodys, it allows at most one more element from each later sequence and at most one more evaluation of the following bodys. Among the bodys, besides stopping the iteration and preventing later body evaluations, a #:break guard-expr or #:final guard-expr clause starts a new internal-definition context.

In the case of list and stream sequences, the for form itself does not keep each element reachable. If a list or stream produced by a seq-expr is otherwise unreachable, and if the for body can no longer reference an id for a list element, then the element is subject to garbage collection. The make-do-sequence sequence constructor supports additional sequences that behave like lists and streams in this way.

Examples:

> > (for ([i '(1 2 3)]
> [j "abc"]
> #:when (odd? i)
> [k #(#t #f)])
> (display (list i j k)))
> (1 a #t)(1 a #f)(3 c #t)(3 c #f)
> > (for ([(i j) #hash(("a" . 1) ("b" . 20))])
> (display (list i j)))
> (b 20)(a 1)
> > (for ([i '(1 2 3)]
> [j "abc"]
> #:break (not (odd? i))
> [k #(#t #f)])
> (display (list i j k)))
> (1 a #t)(1 a #f)
> > (for ([i '(1 2 3)]
> [j "abc"]
> #:final (not (odd? i))
> [k #(#t #f)])
> (display (list i j k)))
> (1 a #t)(1 a #f)(2 b #t)
> > (for ([i '(1 2 3)]
> [j "abc"]
> [k #(#t #f)])
> #:break (not (or (odd? i) k))
> (display (list i j k)))
> (1 a #t)
> > (for ()
> (display "here"))
> here
> > (for ([i '()])
> (error "doesn't get here"))

Changed in version 6.7.0.4 of package base: Added support for the optional second result.

> syntax (for/list (for-clause ...) body-or-break ... body)

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. When evaluation of a body is skipped due to a #:when or #:unless clause, the result list includes no corresponding element.

Examples:

> > (for/list ([i '(1 2 3)]
> [j "abc"]
> #:when (odd? i)
> [k #(#t #f)])
> (list i j k))
> '((1 #\a #t) (1 #\a #f) (3 #\c #t) (3 #\c #f))
> > (for/list ([i '(1 2 3)]
> [j "abc"]
> #:break (not (odd? i))
> [k #(#t #f)])
> (list i j k))
> '((1 #\a #t) (1 #\a #f))
> > (for/list () 'any)
> '(any)
> > (for/list ([i '()])
> (error "doesn't get here"))
> '()

> syntax (for/vector maybe-length (for-clause ...) body-or-break ... body)
> maybe-length |  | = |  |
> |  | | |  | #:length length-expr
> |  | | |  | #:length length-expr #:fill fill-expr
> | length-expr |  | : |  | exact-nonnegative-integer?

Iterates like for/list, but results are accumulated into a vector instead of a list.

If the optional #:length clause is specified, the result of length-expr determines the length of the result vector. In that case, the iteration can be performed more efficiently, and it terminates when the vector is full or the requested number of iterations have been performed, whichever comes first. If length-expr specifies a length longer than the number of iterations, then the remaining slots of the vector are initialized to the value of fill-expr, which defaults to 0 (i.e., the default argument of make-vector).

Examples:

> > (for/vector ([i '(1 2 3)]) (number->string i))
> '#("1" "2" "3")
> > (for/vector #:length 2 ([i '(1 2 3)]) (number->string i))
> '#("1" "2")
> > (for/vector #:length 4 ([i '(1 2 3)]) (number->string i))
> '#("1" "2" "3" 0)
> > (for/vector #:length 4 #:fill "?" ([i '(1 2 3)]) (number->string i))
> '#("1" "2" "3" "?")

The for/vector form may allocate a vector and mutate it after each iteration of body, which means that capturing a continuation during body and applying it multiple times may mutate a shared vector.

> syntax (for/hash (for-clause ...) body-or-break ... body)
> syntax (for/hasheq (for-clause ...) body-or-break ... body)
> syntax (for/hasheqv (for-clause ...) body-or-break ... body)

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:

> > (for/hash ([i '(1 2 3)])
> (values i (number->string i)))
> '#hash((1 . "1") (2 . "2") (3 . "3"))

> syntax (for/and (for-clause ...) body-or-break ... 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
> > (for/and ([i '(1 2 3 4)])
> i)
> 4
> > (for/and ([i '(1 2 3 4)])
> #:break (= i 3)
> i)
> 2
> > (for/and ([i '()])
> (error "doesn't get here"))
> #t

> syntax (for/or (for-clause ...) body-or-break ... 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
> > (for/or ([i '(1 2 3 4)])
> i)
> 1
> > (for/or ([i '()])
> (error "doesn't get here"))
> #f

> syntax (for/sum (for-clause ...) body-or-break ... body)

Iterates like for, but each result of the last body is accumulated into a result with +.

Example:

> > (for/sum ([i '(1 2 3 4)]) i)
> 10

> syntax (for/product (for-clause ...) body-or-break ... body)

Iterates like for, but each result of the last body is accumulated into a result with *.

Example:

> > (for/product ([i '(1 2 3 4)]) i)
> 24

> > syntax
> > (for/lists (id ... maybe-result)
> > (for-clause ...)
> > body-or-break ... body)
> maybe-result |  | = |  |
> |  | | |  | #:result result-expr

Similar to for/list, but the last body expression should produce as many values as given ids. The ids are bound to the lists accumulated so far in the for-clauses and bodys.

If a result-expr is provided, it is used as with for/fold when iteration terminates; otherwise, the result is as many lists as supplied ids

Examples:

> > (for/lists (l1 l2 l3)
> ([i '(1 2 3)]
> [j "abc"]
> #:when (odd? i)
> [k #(#t #f)])
> (values i j k))
> '(1 1 3 3)
> '(#\a #\a #\c #\c)
> '(#t #f #t #f)
> > (for/lists (acc)
> ([x '(tvp tofu seitan tvp tofu)]
> #:unless (member x acc))
> x)
> '(tvp tofu seitan)
> > (for/lists (firsts seconds #:result (list firsts seconds))
> ([pr '((1 . 2) (3 . 4) (5 . 6))])
> (values (car pr) (cdr pr)))
> '((1 3 5) (2 4 6))

Changed in version 7.1.0.2 of package base: Added the #:result form.

> syntax (for/first (for-clause ...) body-or-break ... body)

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.

Examples:

> > (for/first ([i '(1 2 3 "x")]
> #:when (even? i))
> (number->string i))
> "2"
> > (for/first ([i '()])
> (error "doesn't get here"))
> #f

> syntax (for/last (for-clause ...) body-or-break ... body)

Iterates like for, but the for/last result is the (single) result of the last evaluation of body. If the body is never evaluated, then the result of the for/last expression is #f.

Examples:

> > (for/last ([i '(1 2 3 4 5)]
> #:when (even? i))
> (number->string i))
> "4"
> > (for/last ([i '()])
> (error "doesn't get here"))
> #f

> > syntax
> > (for/fold ([accum-id init-expr] ... maybe-result) (for-clause ...)
> > body-or-break ... body)
> maybe-result |  | = |  |
> |  | | |  | #:result result-expr

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, if a result-expr is provided then the result of the for/fold is the result of evaluating result-expr (with accum-ids in scope and bound to their final values), otherwise the results of the for/fold expression are the accumulator values.

An accum-id and a binding from a for-clause can be the same identifier. In that case, the accum-id binding shadows the one in a for-clause within the body-or-break and body forms (even though, syntactically, a for-clause is closer to to the body).

Examples:

> > (for/fold ([sum 0]
> [rev-roots null])
> ([i '(1 2 3 4)])
> (values (+ sum i) (cons (sqrt i) rev-roots)))
> 10
> '(2 1.7320508075688772 1.4142135623730951 1)
> > (for/fold ([acc '()]
> [seen (hash)]
> #:result (reverse acc))
> ([x (in-list '(0 1 1 2 3 4 4 4))])
> (cond
> [(hash-ref seen x #f)
> (values acc seen)]
> [else (values (cons x acc)
> (hash-set seen x #t))]))
> '(0 1 2 3 4)

Changed in version 6.11.0.1 of package base: Added the #:result form.

> syntax (for* (for-clause ...) body-or-break ... body)

Like for, but with an implicit #:when #t between each pair of for-clauses, so that all sequence iterations are nested.

Example:

> > (for* ([i '(1 2)]
> [j "ab"])
> (display (list i j)))
> (1 a)(1 b)(2 a)(2 b)

> syntax (for*/list (for-clause ...) body-or-break ... body)
> syntax (for*/lists (id ... maybe-result) (for-clause ...) body-or-break ... body)
> syntax (for*/vector maybe-length (for-clause ...) body-or-break ... body)
> syntax (for*/hash (for-clause ...) body-or-break ... body)
> syntax (for*/hasheq (for-clause ...) body-or-break ... body)
> syntax (for*/hasheqv (for-clause ...) body-or-break ... body)
> syntax (for*/and (for-clause ...) body-or-break ... body)
> syntax (for*/or (for-clause ...) body-or-break ... body)
> syntax (for*/sum (for-clause ...) body-or-break ... body)
> syntax (for*/product (for-clause ...) body-or-break ... body)
> syntax (for*/first (for-clause ...) body-or-break ... body)
> syntax (for*/last (for-clause ...) body-or-break ... body)
> > syntax
> > (for*/fold ([accum-id init-expr] ... maybe-result) (for-clause ...)
> > body-or-break ... body)

Like for/list, etc., but with the implicit nesting of for*.

Example:

> > (for*/list ([i '(1 2)]
> [j "ab"])
> (list i j))
> '((1 #\a) (1 #\b) (2 #\a) (2 #\b))

##### 3.18.2`` Deriving New Iteration Forms

> > syntax
> > (for/fold/derived orig-datum
> > ([accum-id init-expr] ... maybe-result) (for-clause ...)
> > body-or-break ... body)

Like for/fold, but the extra orig-datum is used as the source for all syntax errors.

Examples:

> > (define-syntax (for/digits stx)
> (syntax-case stx ()
> [(_ clauses body ... tail-expr)
> (with-syntax ([original stx])
> #'(let-values
> ([(n k)
> (for/fold/derived
> original ([n 0] [k 1])
> clauses
> body ...
> (values (+ n (* tail-expr k)) (* k 10)))])
> n))]))
> ; If we misuse for/digits, we can get good error reporting
> ; because the use of orig-datum allows for source correlation:
> > (for/digits
> [a (in-list '(1 2 3))]
> [b (in-list '(4 5 6))]
> (+ a b))
> eval:3:0: for/digits: bad sequence binding clause
> at: a
> in: (for/digits (a (in-list (quote (1 2 3)))) (b (in-list
> (quote (4 5 6)))) (+ a b))
> > (for/digits
> ([a (in-list '(1 2 3))]
> [b (in-list '(2 4 6))])
> (+ a b))
> 963
> ; Another example: compute the max during iteration:
> > (define-syntax (for/max stx)
> (syntax-case stx ()
> [(_ clauses body ... tail-expr)
> (with-syntax ([original stx])
> #'(for/fold/derived original
> ([current-max -inf.0])
> clauses
> body ...
> (define maybe-new-max tail-expr)
> (if (> maybe-new-max current-max)
> maybe-new-max
> current-max)))]))
> > (for/max ([n '(3.14159 2.71828 1.61803)]
> [s '(-1 1 1)])
> (* n s))
> 2.71828

Changed in version 6.11.0.1 of package base: Added the #:result form.

}

> > syntax
> > (for*/fold/derived orig-datum
> > ([accum-id init-expr] ... maybe-result) (for-clause ...)
> > body-or-break ... body)

Like for*/fold, but the extra orig-datum is used as the source for all syntax errors.

Examples:

> > (define-syntax (for*/digits stx)
> (syntax-case stx ()
> [(_ clauses body ... tail-expr)
> (with-syntax ([original stx])
> #'(let-values
> ([(n k)
> (for*/fold/derived original ([n 0] [k 1])
> clauses
> body ...
> (values (+ n (* tail-expr k)) (* k 10)))])
> n))]))
> > (for*/digits
> [ds (in-list '((8 3) (1 1)))]
> [d (in-list ds)]
> d)
> eval:8:0: for*/digits: bad sequence binding clause
> at: ds
> in: (for*/digits (ds (in-list (quote ((8 3) (1 1))))) (d
> (in-list ds)) d)
> > (for*/digits
> ([ds (in-list '((8 3) (1 1)))]
> [d (in-list ds)])
> d)
> 1138

Changed in version 6.11.0.1 of package base: Added the #:result form.

}

> > syntax
> > (define-sequence-syntax id
> > expr-transform-expr
> > clause-transform-expr)
> > | expr-transform-expr |  | : |  |
> > (or/c (-> identifier?)
> > (syntax? . -> . syntax?))
> > | clause-transform-expr |  | : |  | (syntax? . -> . syntax?)

Defines id as syntax. An (id . rest) form is treated specially when used to generate a sequence in a for-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 for-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 for-clause to replace the given one. The new clause might use :do-in. To protect identifiers in the result of clause-transform-expr, use for-clause-syntax-protect instead of syntax-protect.

Examples:

> > (define (check-nat n)
> (unless (exact-nonnegative-integer? n)
> (raise-argument-error 'in-digits "exact-nonnegative-integer?" n)))
> > (define-sequence-syntax in-digits
> (lambda () #'in-digits/proc)
> (lambda (stx)
> (syntax-case stx ()
> [[(d) (_ nat)]
> #'[(d)
> (:do-in
> ([(n) nat])
> (check-nat n)
> ([i n])
> (not (zero? i))
> ([(j d) (quotient/remainder i 10)])
> #true
> [j])]]
> [_ #f])))
> > (define (in-digits/proc n)
> (for/list ([d (in-digits n)]) d))
> > (for/list ([d (in-digits 1138)]) d)
> '(8 3 1 1)
> > (map in-digits (list 137 216))
> '((7 3 1) (6 1 2))

> > syntax
> > (: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 for-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.

For an example of :do-in, see define-sequence-syntax.

> procedure (for-clause-syntax-protect stx) → syntax?
> stx : syntax?

Provided for-syntax: Like syntax-protect, but allows the for expander to disarm the result syntax object, and arms the pieces of a clause instead of the entire syntax object.

Use this function to protect the result of a clause-transform-expr that is bound by define-sequence-syntax.

##### 3.18.3`` Do Loops

> > syntax
> > (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 have been bound, the 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>.

top ← prev up next →