For Loop Desugaring (was: return when desugaring to closures)
Brendan Eich
brendan at mozilla.com
Mon Oct 13 22:28:20 PDT 2008
On Oct 13, 2008, at 7:48 PM, Mark S. Miller wrote:
> On Mon, Oct 13, 2008 at 5:00 PM, Jon Zeppieri <jaz at bu.edu> wrote:
>> 1) for (var i = 0; i < len; i++) ... continues to mean what it
>> means in ES3.
>> 2) for (let i = 0; i < len; i++) ... has the proper scope for 'i'
>> (which you reiterated above), *and* 'i' is rebound -- not mutated --
>> on each iteration.
>> 3) The rewrite rules are the *same,* regardless of whether it's a
>> "for
>> (var ...)" or a "for (let ...)" loop.
>>
>> At least, that's what I took Mark to mean. He can correct me if
>> I'm wrong.
>
>
> You're right. However, the desugaring is more complex than I expected.
> Thanks for asking me to write it down.
>
> for (<keyword> <varName> = <initExpr>; <testExpr>; <updateExpr>)
> { <body> }
>
> desugars to (hygienic renaming aside):
>
> breakTarget: {
> const loop = lambda(iter = <initExpr>) {
> <keyword> <varName> = iter;
> if (! <testExpr>) { break breakTarget; }
> continueTarget: { <body> }
> lambda(iter2 = <varName>) {
> <keyword> <varName> = iter2;
> <updateExpr>;
> loop(<varName>);
> }();
> };
> loop();
> }
>
> I believe this meets all your requirements.
Requirement 3 is met because var hoists to the enclosing function.
This is the part I missed -- well done.
Note that continue; in body translates to break continueTarget; and
break; translates to break breakTarget; -- you knew that ;-).
> However, in contradiction
> to my original claim, one couldn't usefully say "const" instead of
> "let" with a for(;;) loop.
Why not usefully? It's true the consts do not hoist to leave an effect
in the variable object, but they do ensure const-ness. The body and
update cannot mutate the nearest <varName> binding. This is sometimes
useful and existing const implementations allow for (const...). I do
not think it should be rejected just yet.
/be
More information about the Es-discuss
mailing list