in-value: fix inlined binding
The inlined version of `in-value` in a `for` form did not bind the left-hand identifier at the right layer relative to other bindings in `for/fold`, which caused the inlined `in-value` to behave differently than a non-inlined `in-value`. Confusing about this `in-value`, in turn, had led to incorrect documentation on `for/fold`. It would be nice to clean up a little more of the evaluator and availability of bindings in `for/fold`, but doing so runs a significant risk of breaking existing code (unlike fixing `in-value`, which behaved even worse and where the repair seems less likely to break existing programs). Closes #1659 (again)
This commit is contained in:
parent
09480c86e8
commit
94725ffb4e
|
@ -374,19 +374,19 @@ terminates, if a @racket[result-expr] is provided then the result of the
|
||||||
]
|
]
|
||||||
|
|
||||||
The binding and evaluation order of @racket[accum-id]s and
|
The binding and evaluation order of @racket[accum-id]s and
|
||||||
@racket[init-expr]s does not follow the textual, left-to-right order
|
@racket[init-expr]s do not completely follow the textual,
|
||||||
relative to the @racket[for-clause]s . Instead, the sequence
|
left-to-right order relative to the @racket[for-clause]s. Instead, the
|
||||||
expressions in @racket[for-clause]s that determine the outermost
|
sequence expressions in @racket[for-clause]s that determine the
|
||||||
iteration are evaluated first, the associated identifiers are bound,
|
outermost iteration are evaluated first, then the @racket[init-expr]s
|
||||||
and then the @racket[init-expr]s are evaluated and the
|
are evaluated and the @racket[accum-id]s are bound, and finally the
|
||||||
@racket[accum-id]s are bound. One consequence is that the
|
outermost iteration's identifiers are bound. One consequence is that
|
||||||
@racket[accum-id]s are not bound in @racket[for-clause]s for the
|
the @racket[accum-id]s are not bound in @racket[for-clause]s for the
|
||||||
outermost initialization. Another consequence is that when a
|
outermost initialization. At the same time, when a @racket[accum-id]
|
||||||
@racket[accum-id] is used as a @racket[for-clause] binding for the
|
is used as a @racket[for-clause] binding for the outermost iteration,
|
||||||
outermost iteration, the @racket[for-clause] binding is shadowed in
|
the @racket[for-clause] binding shadows the @racket[accum-id] binding
|
||||||
the loop body (even though, syntactically, a @racket[for-clause] is
|
in the loop body (which is what you would expect syntactically).
|
||||||
closer to the body). A fresh variable for each @racket[accum-id] (at a
|
A fresh variable for each @racket[accum-id] (at a
|
||||||
fresh location) is bound to in each nested iteration created by a
|
fresh location) is bound in each nested iteration that is created by a
|
||||||
later group for @racket[for-clause]s (after a @racket[#:when] or
|
later group for @racket[for-clause]s (after a @racket[#:when] or
|
||||||
@racket[#:unless], for example).
|
@racket[#:unless], for example).
|
||||||
|
|
||||||
|
|
|
@ -461,6 +461,25 @@
|
||||||
(test 13 next)
|
(test 13 next)
|
||||||
(test #f more?))
|
(test #f more?))
|
||||||
|
|
||||||
|
(test 1 'in-value-bind-correctly (for/fold ([x #f])
|
||||||
|
([x (in-value 1)])
|
||||||
|
x))
|
||||||
|
(test 2 'in-value-bind-correctly (for/fold ([x #f])
|
||||||
|
([x (values (in-value 2))])
|
||||||
|
x))
|
||||||
|
|
||||||
|
(let ([x 'out]
|
||||||
|
[prints '()])
|
||||||
|
(for/fold ([x (begin
|
||||||
|
(set! prints (cons (list 'top x) prints))
|
||||||
|
'top)])
|
||||||
|
([x (in-list (begin
|
||||||
|
(set! prints (cons (list 'rhs x) prints))
|
||||||
|
(list 1 2 3)))])
|
||||||
|
(set! prints (cons x prints))
|
||||||
|
x)
|
||||||
|
(test '(3 2 1 (top out) (rhs out)) values prints))
|
||||||
|
|
||||||
;; check ranges on `in-vector', especially as a value
|
;; check ranges on `in-vector', especially as a value
|
||||||
(test '() 'in-empty-vector (let ([v (in-vector '#())]) (for/list ([e v]) e)))
|
(test '() 'in-empty-vector (let ([v (in-vector '#())]) (for/list ([e v]) e)))
|
||||||
(test '() 'in-empty-vector (let ([v (in-vector '#() 0)]) (for/list ([e v]) e)))
|
(test '() 'in-empty-vector (let ([v (in-vector '#() 0)]) (for/list ([e v]) e)))
|
||||||
|
|
|
@ -2309,8 +2309,8 @@
|
||||||
(lambda () #'in-value)
|
(lambda () #'in-value)
|
||||||
(lambda (stx)
|
(lambda (stx)
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
[[(id) (_ expr)]
|
[[<(id) (_ expr)]
|
||||||
#'[(id) (:do-in ([(id) expr]) #t () #t () #t #f ())]]
|
#'[(id) (:do-in ([(id*) expr]) #t () #t ([(id) id*]) #t #f ())]]
|
||||||
[_ #f])))
|
[_ #f])))
|
||||||
|
|
||||||
(define-sequence-syntax *in-producer
|
(define-sequence-syntax *in-producer
|
||||||
|
|
Loading…
Reference in New Issue
Block a user