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
|
||||
@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
|
||||
@racket[init-expr]s do not completely 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, then the @racket[init-expr]s
|
||||
are evaluated and the @racket[accum-id]s are bound, and finally the
|
||||
outermost iteration's identifiers are bound. One consequence is that
|
||||
the @racket[accum-id]s are not bound in @racket[for-clause]s for the
|
||||
outermost initialization. At the same time, when a @racket[accum-id]
|
||||
is used as a @racket[for-clause] binding for the outermost iteration,
|
||||
the @racket[for-clause] binding shadows the @racket[accum-id] binding
|
||||
in the loop body (which is what you would expect syntactically).
|
||||
A fresh variable for each @racket[accum-id] (at 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
|
||||
@racket[#:unless], for example).
|
||||
|
||||
|
|
|
@ -461,6 +461,25 @@
|
|||
(test 13 next)
|
||||
(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
|
||||
(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)))
|
||||
|
|
|
@ -2309,8 +2309,8 @@
|
|||
(lambda () #'in-value)
|
||||
(lambda (stx)
|
||||
(syntax-case stx ()
|
||||
[[(id) (_ expr)]
|
||||
#'[(id) (:do-in ([(id) expr]) #t () #t () #t #f ())]]
|
||||
[[<(id) (_ expr)]
|
||||
#'[(id) (:do-in ([(id*) expr]) #t () #t ([(id) id*]) #t #f ())]]
|
||||
[_ #f])))
|
||||
|
||||
(define-sequence-syntax *in-producer
|
||||
|
|
Loading…
Reference in New Issue
Block a user