improve docs on issues with for
bindings
See #3378: The possibility of mutation should be considered in `:do-in` in somme rare cases, while it's not clear that there's anything better to be done for mutation of the list accumulators in `for/lists`. At least make the pitfalls clearer in the documentation.
This commit is contained in:
parent
fb9bd97844
commit
8ca49775b4
|
@ -268,12 +268,17 @@ is accumulated into a result with @racket[*].
|
|||
Similar to @racket[for/list], but the last @racket[body] expression
|
||||
should produce as many values as given @racket[id]s.
|
||||
The @racket[id]s are bound to
|
||||
the lists accumulated so far in the @racket[for-clause]s and
|
||||
the reversed lists accumulated so far in the @racket[for-clause]s and
|
||||
@racket[body]s.
|
||||
|
||||
If a @racket[result-expr] is provided, it is used as with @racket[for/fold]
|
||||
when iteration terminates;
|
||||
otherwise, the result is as many lists as supplied @racket[id]s
|
||||
otherwise, the result is as many lists as supplied @racket[id]s.
|
||||
|
||||
The scope of @racket[id] bindings is the same as for accumulator
|
||||
identifiers in @racket[for/fold]. Mutating a @racket[id] affects the
|
||||
accumulated lists, and mutating it in a way that produces a non-list
|
||||
can cause a final @racket[reverse] for each @racket[id] to fail.
|
||||
|
||||
@examples[
|
||||
(for/lists (l1 l2 l3)
|
||||
|
@ -343,12 +348,6 @@ terminates, if a @racket[result-expr] is provided then the result of the
|
|||
otherwise the results of the @racket[for/fold] expression are the
|
||||
accumulator values.
|
||||
|
||||
An @racket[accum-id] and a binding from a @racket[for-clause] can be
|
||||
the same identifier. In that case, the @racket[accum-id] binding
|
||||
shadows the one in a @racket[for-clause] within the
|
||||
@racket[body-or-break] and @racket[body] forms (even though,
|
||||
syntactically, a @racket[for-clause] is closer to the body).
|
||||
|
||||
@examples[
|
||||
(for/fold ([sum 0]
|
||||
[rev-roots null])
|
||||
|
@ -365,6 +364,24 @@ syntactically, a @racket[for-clause] is closer to the body).
|
|||
[else (values (cons x acc)
|
||||
(hash-set seen x #t))]))
|
||||
]
|
||||
|
||||
The binding and evaluation order of @racket[accum-id]s and
|
||||
@racket[init-expr]s does not follow the textual, left-to-right order
|
||||
relative to the @racket[for-clause]s . Instead, the sequence
|
||||
expressions in @racket[for-clause]s that determine the outermost
|
||||
iteration are evaluated first, the associated identifiers are bound,
|
||||
and then the @racket[init-expr]s are evaluated and the
|
||||
@racket[accum-id]s are bound. One consequence is that the
|
||||
@racket[accum-id]s are not bound in @racket[for-clause]s for the
|
||||
outermost initialization. Another consequence is that when a
|
||||
@racket[accum-id] is used as a @racket[for-clause] binding for the
|
||||
outermost iteration, the @racket[for-clause] binding is shadowed in
|
||||
the loop body (even though, syntactically, a @racket[for-clause] is
|
||||
closer to the body). A fresh variable for each @racket[accum-id] (at a
|
||||
fresh location) is bound to in each nested iteration created by a
|
||||
later group for @racket[for-clause]s (after a @racket[#:when] or
|
||||
@racket[#:unless], for example).
|
||||
|
||||
@history[#:changed "6.11.0.1" @elem{Added the @racket[#:result] form.}]
|
||||
}
|
||||
|
||||
|
@ -766,6 +783,12 @@ context of the @racket[:do-in] use. The identifiers bound by the
|
|||
@racket[for] clause are typically part of the @racket[([(inner-id ...)
|
||||
inner-expr] ...)] section.
|
||||
|
||||
Beware that @racket[_body-bindings] and @racket[_done-expr] can
|
||||
contain arbitrary expressions, potentially including @racket[set!] on
|
||||
@racket[outer-id] or @racket[inner-id] identifiers if they are visible
|
||||
in the original @racket[for] form, so beware of depending on such
|
||||
identifiers in @racket[post-guard] and @racket[loop-arg].
|
||||
|
||||
The actual @racket[loop] binding and call has additional loop
|
||||
arguments to support iterations in parallel with the @racket[:do-in]
|
||||
form, and the other pieces are similarly accompanied by pieces from
|
||||
|
|
|
@ -2278,7 +2278,9 @@
|
|||
'in-dir/no-arg
|
||||
(parameterize ([current-directory tmp-dir])
|
||||
(for/hash ([f (in-directory)])
|
||||
(values f #t))))
|
||||
(let ([real-f f])
|
||||
(set! f 'trying-to-break-in-directory)
|
||||
(values real-f #t)))))
|
||||
(define (mk) (in-directory))
|
||||
(test ht
|
||||
'in-dir/no-arg/outline
|
||||
|
|
|
@ -643,6 +643,14 @@
|
|||
(define-syntax (m stx) #'0)
|
||||
m))
|
||||
|
||||
(test '(bad 1)
|
||||
'for/lists-weird-set!
|
||||
(for/lists (acc)
|
||||
([v (in-range 2)])
|
||||
(unless (zero? v)
|
||||
(set! acc '(bad)))
|
||||
v))
|
||||
|
||||
;; for should discard any results and return void
|
||||
(test (void) 'for-0-values (for ([x '(1 2 3)] [y '(a b c)]) (values)))
|
||||
(test (void) 'for*-0-values (for* ([x '(1 2 3)] [y '(a b c)]) (values)))
|
||||
|
|
|
@ -2377,7 +2377,7 @@
|
|||
([(d) (car l)])
|
||||
#true
|
||||
#true
|
||||
[(next-body l d init-dir use-dir?)])]]
|
||||
[(next-body l (car l) init-dir use-dir?)])]]
|
||||
[_ #f])))
|
||||
|
||||
)
|
||||
|
|
|
@ -274,7 +274,8 @@
|
|||
"../../include/racketcsboot.h"
|
||||
#t)
|
||||
(copy-file (build-path scheme-dir machine "boot" machine "scheme.h")
|
||||
"../../include//chezscheme.h")
|
||||
"../../include/chezscheme.h"
|
||||
#t)
|
||||
|
||||
(parameterize ([current-directory "mzstart"])
|
||||
(system*! "msbuild"
|
||||
|
|
Loading…
Reference in New Issue
Block a user