January 19 meeting notes

Jon Zeppieri zeppieri at gmail.com
Fri Jan 20 14:08:31 PST 2012

On Fri, Jan 20, 2012 at 7:25 AM, Grant Husbands <esdiscuss at grant.x43.net> wrote:
> Jon Zeppieri wrote:
>> Is there a version of this desugaring that deals with recursive
>> bindings in the initializer expression of the loop?
> How about something like this?
> (given for (let <varName> = <initExpr>; <testExpr>; <updateExpr>) { <body> } )
> {
>  let <varName> = <initExpr>;
>  while(true) {
>    if (!<testExpr>) { break breakTarget; }
>    let <tempVar> = <varName>;
>    {
>      // There might be a better way to copy values to/from shadowed variables
>      // (using temporaries seems a bit weak)
>      let <varName> = <tempVar>;
>      continueTarget: { <body> }
>      <tempVar> = <varName>;
>    }
>    <varName> = <tempVar>;
>    <updateExpr>;
>  }
> }
> That way, all of the variable references in initExpr, testExpr and
> updateExpr refer to a singular copy and all of the variable references
> in body refer to the iteration-scoped ones.

It doesn't satisfy Desirable Property #3 from the previously cited email:

> 3) The rewrite rules are the *same,* regardless of whether it's a "for
> (var ...)" or a "for (let ...)" loop.

But that's the least important property.

> So, looking at your example:
>> for (let [i, inc] = [0, function() {i++;}]; i < n; inc()) ...
> I think it now has the desired behaviour. However, people calling inc
> from inside the body will still be surprised.

Yeah, that's a problem.

> I think solving that
> probably requires something more advanced than a desugaring, as it
> means the loop variables captured by that function (or, alternatively,
> ones captured inside the body) need to point at different variables at
> different times.

That's my suspicion, as well, and I'm curious whether this affects
TC39 members' opinion. It's not entirely clear from Brendan's email
what caused him, Waldemar, and David Herman to "hop off the fence" in
support of the fresh-binding-per-iteration approach, but it sounds to
me like they were initially concerned about needing to specify a
complicated semantics and were persuaded by MarkM's argument that the
problem could be solved syntactically.

> There's also an abstraction leakage if one breaks in the body, in that
> the inner <varName> doesn't get copied to the outer one. All in all,
> not a great desugaring, but I thought it might be worth offering.
> Maybe disallowing capture in the for (let ...;...;...) head would be easier.

I still think there's something misleading about taking a loop with an
imperative update and re-binding behind the scenes, despite the fact
that the problem it's trying to solve is definitely a real problem
(I've been bitten by it myself). It's one thing if the difference
really isn't observable except in the case where a closure captures
the iteration variable (as Sam suggests), since it's hard to imagine
anyone wanting the current binding behavior in that case. But the
recursive binding cases make me a bit uneasy.


> Regards,
> Grant Husbands.

More information about the es-discuss mailing list