add #:unless' to for'

This commit is contained in:
Matthew Flatt 2011-06-09 16:34:35 -07:00
parent bbd98528ba
commit 460504c852
4 changed files with 32 additions and 7 deletions

View File

@ -1224,6 +1224,18 @@
(#:when expr . rest) . body)
#'(frm [orig-stx nested? #t binds] ([fold-var fold-init] ...)
(#:when expr . rest) . body)]
;; Negative guard case, no pending emits:
[(_ [orig-stx nested? #f ()] ([fold-var fold-init] ...) (#:unless expr . rest) . body)
#'(let ([fold-var fold-init] ...)
(if expr
(values* fold-var ...)
(for/foldX/derived [orig-stx nested? #f ()]
([fold-var fold-var] ...) rest . body)))]
;; Negative guard case, pending emits need to be flushed first
[(frm [orig-stx nested? #f binds] ([fold-var fold-init] ...)
(#:unless expr . rest) . body)
#'(frm [orig-stx nested? #t binds] ([fold-var fold-init] ...)
(#:unless expr . rest) . body)]
;; Convert single-value form to multi-value form:
[(_ [orig-stx nested? #f binds] fold-bind ([id rhs] . rest) . body)
(identifier? #'id)

View File

@ -132,7 +132,8 @@ A more complete syntax of @racket[for] is
(for (clause ...)
body ...+)
([clause [id sequence-expr]
(code:line #:when boolean-expr)])
(code:line #:when boolean-expr)
(code:line #:unless boolean-expr)])
]{}
When multiple @racket[[_id _sequence-expr]] clauses are provided
@ -194,6 +195,10 @@ mutually nested, instead of in parallel, even with @racket[for].
(printf "~a Chapter ~a. ~a\n" book i chapter))
]
An @racket[#:unless] clause is analogus to a @racket[#:when] clause, but
the @racket[_body]s evaluate only when the @racket[_boolean-expr]
produces a false value.
@section{@racket[for/list] and @racket[for*/list]}
The @racket[for/list] form, which has the same syntax as @racket[for],

View File

@ -14,7 +14,8 @@ The @scheme[for] iteration forms are based on SRFI-42
@defform/subs[(for (for-clause ...) body ...+)
([for-clause [id seq-expr]
[(id ...) seq-expr]
(code:line #:when guard-expr)])
(code:line #:when guard-expr)
(code:line #:unless guard-expr)])
#:contracts ([seq-expr sequence?])]{
Iteratively evaluates @scheme[body]. The @scheme[for-clause]s
@ -45,7 +46,7 @@ a sequence containing a single element. All of the @scheme[id]s must
be distinct according to @scheme[bound-identifier=?].
If any @scheme[for-clause] has the form @scheme[#:when guard-expr],
then only the preceding clauses (containing no @scheme[#:when])
then only the preceding clauses (containing no @scheme[#:when] or @scheme[#:unless])
determine iteration as above, and the @scheme[body] is effectively
wrapped as
@ -54,7 +55,9 @@ wrapped as
(for (for-clause ...) body ...+))
]
using the remaining @scheme[for-clauses].
using the remaining @scheme[for-clauses]. A @scheme[for-clause] of
the form @scheme[#:unless guard-expr] corresponds to the same transformation
with @racket[unless] in place of @racket[when].
@examples[
(for ([i '(1 2 3)]
@ -74,6 +77,9 @@ using the remaining @scheme[for-clauses].
@scheme[for], but that the last expression in the @scheme[body]s must
produce a single value, and the result of the @scheme[for/list]
expression is a list of the results in order.
When evaluation of a @scheme[body] is skipped due to a @racket[#:when]
or @racket[#:unless] clause, the result list includes no corresponding
element.
@examples[
(for/list ([i '(1 2 3)]
@ -89,9 +95,8 @@ expression is a list of the results in order.
@defform*[((for/vector (for-clause ...) body ...+)
(for/vector #:length length-expr (for-clause ...) body ...+))]{
Iterates like @scheme[for], but the last expression
in the @scheme[body]s must produce a single value, which is placed in
the corresponding slot of a vector. If the optional @scheme[#:length]
Iterates like @scheme[for/list], but the result are accumulated into
a vector instead of a list. If the optional @scheme[#:length]
form is used, then @scheme[length-expr] must evaluate to an
@scheme[exact-nonnegative-integer?], and the result vector is
constructed with this length. In this case, the iteration can be

View File

@ -44,6 +44,9 @@
(test (map (lambda (x) #t) `seq) 'gen (for*/list ([i gen][b '(#t)]) b))
(test (append `seq `seq) 'gen (for*/list ([b '(#f #t)][i gen]) i))
(test (append `seq `seq) 'gen (for/list ([b '(#f #t)] #:when #t [i gen]) i))
(test (append `seq `seq) 'gen (for/list ([b '(#t #t #f)] #:when b [i gen]) i))
(test (append `seq `seq) 'gen (for/list ([b '(#f #t)] #:unless #f [i gen]) i))
(test (append `seq `seq) 'gen (for/list ([b '(#f #f #t)] #:unless b [i gen]) i))
(test `seq 'gen (let ([g gen]) (for/list ([i g]) i)))
(test `seq 'gen (let ([r null])
(for ([i gen]) (set! r (cons i r)))