For loops with per-iteration variables
David-Sarah Hopwood
david.hopwood at industrial-designers.co.uk
Mon Oct 13 21:47:16 PDT 2008
David-Sarah Hopwood wrote:
> David-Sarah Hopwood wrote:
>> David-Sarah Hopwood wrote:
>>> Mark S. Miller wrote:
>>>> [...] I recommend the per-iteration view. If we can
>>>> agree quickly on per-iteration, then
>>>>
>>>> for (const x = ...) {...x...}
>>>>
>>>> should be allowed in ES3.1 (whether or not const hoists to block
>>>> start). After ES3.1
>>>>
>>>> for (const i :T[i] = ...) {...; a[i] = function(){...i...}; ...}
>>>>
>>>> would then mean what it should mean. Cool.
>>> Not so fast :-) Consider:
>>>
>>> for (let i = 0; i < 10; i++) { ... }
>>>
>>> In the "i++", which iteration's 'i' is the LeftHandSideExpression
>>> referring to? Or does this expand to something like:
>>> [snip]
>> This expansion is wrong for the case where the body updates i.
>> I'll have to think about it some more.
>
> MarkM is right that it just falls out of the natural tail-recursive
> encoding of a for loop. I got the above expansion wrong by trying to do
> it imperatively, which was silly -- the tail-recursive expansion is much
> simpler:
>
> for (let i = initExpr; condExpr; updateExpr) { body }
> ==>
> { let ($loop = lambda(i) {
> if (condExpr) {
> { body } (updateExpr); $loop(i);
> }
> }) { $loop(initExpr); } }
Argh. Still wrong (the updateExpr updates the previous iteration's
variable, rather than the next iteration's, which means that a closure
that captures the variable in iteration n will end up seeing its value
in iteration n+1). To fix that problem it should be:
for (let i = initExpr; condExpr; updateExpr) { body }
==>
{ let ($loop = lambda(i) {
(updateExpr);
if (condExpr) { { body } $loop(i); }
}, i = initExpr) {
if (condExpr) { { body } $loop(i); }
} }
> This also straightforwardly generalizes to multiple variables.
Yes, it still does.
--
David-Sarah Hopwood
More information about the Es-discuss
mailing list