lexical for-in/for-of loose end
Brendan Eich
brendan at mozilla.org
Mon Feb 6 11:21:13 PST 2012
Grant Husbands wrote:
>> But this is all beyond the spec.
>
> I don't think it is. What Herby's idea and these formulations present
> is a way for let-based loops to have modifications in closures
> captured in the for-head that alter the loop variables in a way that's
> visible to the current loop iteration.
And read back changes from the current iteration.
Yes, I see that a new (novel!) observable semantic model is being
proposed here, not an optimization. At first it seemed Herby was
proposing just the usual optimizations.
I still do not think it's wise to specify in terms of such
pointer-updating reference semantics, not for the body closures that
want to capture loop control variables. But only if closures in the
for-head capture loop variables? That would be Allen's "DWIM" (Do What I
mean) semantics.
DWIM is tempting. Perl is full of it and it can be convenient at first.
It often blows back, badly, due to ambiguity.
> As such, choosing whether or
> not to use these formulations affects the spec.
Agreed, with caution about bending the body closure model around this
prematurely. If we pull it off, probably the body closures can do the
same "optimization" -- but it's not clear we can pull it off.
> I agree that it may indeed be too large a feature, given that
> desugarings can cover the vast majority of use-cases well enough. I
> just thought it worth following the logic through.
Gotcha.
It is tempting to try for this, since it would let a C++-knowing hacker
write a loop like the one you show below, and have it work -- while the
common var-capture pigeon-hole problem would be solved too for
let-bindings captured by body-closures.
>> > Still trying to be sure you intended a unique and dynamic scope for the
>> > initializer (first part) of for(let;;).
>
> In the first version, depending on the definition of "dynamic", yes.
> In the second version, no, though instead closures inside the loop
> body get a similarly 'dynamic' scope.
>
> Here's a longer, still informal version of the second.
>
> Given a loop of this form:
> for (let i = 0, inc = function(){i++}; i<N; inc()) { ... }
> We want the loop to run to completion while ensuring that each closure
> within the body gets a copy of 'i' as it existed in the loop iteration
> in which the closure was created. One way to do that is to keep track
> of the closures that get created during a loop iteration and, at the
> end of the loop iteration, give those closures a new environment
> ([[Scope]]) which is a copy of the old one, but with a clone of the
> current loop body environment record replacing the original.
[snip]
> Probably the biggest issue with the above spec is that it assumes
> envRec inside an environment is reference-like, which it could easily
> not be in current implementations, so this variant would also
> introduce an extra indirection in at least some circumstances.
This is a big issue, I agree.
> I support the two main destructurings under consideration right now
> more than I support the above, though.
Any preference for 0th over 1st iteration scope for closures in INIT
binding initializer expressions?
You and Allen remind me that the whole head needs thought:
for (INIT; TEST; NEXT) BODY
If we do what Andreas suggests, 0th iteration scope for INIT, then TEST
must use BODY scope for the iteration that follows if TEST evaluates
truthy. And NEXT must use a new scope for the next iteration too,
preparing for TEST.
enterblock <V>
INIT
reenterblock // Andreas's suggested 0th iteration scope for INIT
goto L2
L1: BODY
reenterblock
NEXT
L2: TEST
iftrue L1
leaveblock
This is not going to give TEST and NEXT the "DWIM" semantics. Sorry, I'm
sure you get this, I'm just spelling it out to be sure everyone
(including me) gets it.
Is this a problem? I don't know. INIT may want the DWIM semantics, but
TEST and NEXT before it for 2nd through Nth iterations really are more
like parts of the BODY. Why should they form closures that magically
reference "current iteration scope" when called later?
DWIM always falls to ambiguity. What did you mean? I dunno, just do it! :-P
/be
More information about the es-discuss
mailing list