return when desugaring to closures

David-Sarah Hopwood david.hopwood at
Mon Oct 13 13:16:50 PDT 2008

Mark S. Miller wrote:
> On Mon, Oct 13, 2008 at 8:05 AM, David-Sarah Hopwood
> <david.hopwood at> wrote:
>> "for (var ...)" implicitly introduces a block whether or not it
>> is a substatement. This is a wart of C++/C99/Java syntax that
>> we have to live with, since too much code relies on it.
> Yes, but how do we live with it? The only currently allowed case,
> "var" as above, is no problem, since it hoists to the function body
> anyway.

Yes, I should have used "for (let ...)" as the example.

> But what about "let". Do we all agree that in
>     for (let x = ...) {...x...}
>     ... x ...
> the x after the for loop does not refer to the x defined by the for
> loop?

Yes, if this form is allowed. The other options are either to require:

  let x in { for (x = 0; x < 10; x++) {...x...} }
  let x = 0 in { for (; x < 10; x++) {...x...} }

or to add new syntax:

  for x = 0 while {x < 10} with {x++} do { ...x... }

The latter is longer, but it makes more sense to me, because the
scoping is absolutely consistent with the braces. I don't know what
other C/Java/JS-trained programmers will make of it, though.

> A remaining interesting question is whether [in the case of
> "for (let" or "for (const"] the for loop reassigns to
> a single per-for-loop-entry x, or whether it initializes a fresh
> per-iteration x. If the for loop body has a closure that captures x,
> it makes a difference. 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:

  let ($i = 0) {
    for (;
         let (i = $i) {i < 10};
         let (i = $i) {{i++;} $i = i;}} {
      let (i = $i) {...};

? That would work as I think you want, but it seems a bit magical to me.
I could be convinced, though -- do you want to try and make the case for
why there should be a fresh variable per iteration with some concrete

David-Sarah Hopwood

More information about the Es-discuss mailing list