Explicit local copies (was: Re: lexical for-in/for-of loose end)

Herby Vojčík herby at mailbox.sk
Tue Feb 7 10:56:50 PST 2012



Andreas Rossberg wrote:
>>> let a = [], b = [], c = [], d = []
>>> for (int i = 0, f = function(){ return function() { ++i } }; i<  10;
>>> d[i] = function() { return i }, ++i) {
>>>   a[i] = f;
>>>   b[i] = f();
>>>   c[i] = function(){ return i }
>>> }
>
> But note that the environment in b's closures is not the for-loop
> environment. Instead, it is a local environment, whose parent is the
> for-loop environment. To make that case work, it is not enough to be
> able to modify the [[Scope]] environment of closures -- in general,
> you'd need to swap out arbitrary parts of an environment chain.

Oww, that's a problem. Copies are hard here... refs can do it, but no 
one likes them.

> I am fine with either. So far I have favoured
> fresh-variables-per-iteration, but the current discussion has raised
> some doubts in the back of my mind.

This whole discussion leads me to completely different opinion: what 
about to embrace "explicit is better than implicit" for this case, and 
allow let/const without initializer to create local copy of an outer 
variable?

Then, if you need to capture a value, you write it down (I know this 
appeared to avoid capturing by hand in (function (i) { ... })(i), but 
reusing normal blocks to do it may work, wouldn't it?

It disallows some of the ninjutsu (init-closures will work with 
different i than localized closures), but it will be clearly visible:

   let a = [], b = [], c = [], d = [], e = []
   for (int i = 0, f = function(){ return function() { ++i } }; i<  10;
     d[i] = function() { return i }, ++i) {
     a[i] = f; // this
     b[i] = f(); // and this
     c[i] = function(){ return i } // and this work with loop-level i
     {
        let i;
        e[i] = function () { return i; } // this has local i
     }
   }

> /Andreas

There can be even shorter syntax, like
        e[i] = function () let i { return i; } // this has local i
or
        e[i] = function () { let i; return i; } // this has local i
whoch can avoid need of {} block, but it must be thought of if it is 
possible consistently (the former should, the latter may be questionable).

Herby


More information about the es-discuss mailing list