lexical for-in/for-of loose end

Allen Wirfs-Brock allen at wirfs-brock.com
Wed Feb 1 18:54:45 PST 2012


On Feb 1, 2012, at 3:05 PM, Brendan Eich wrote:

> Allen Wirfs-Brock wrote:
>> On Feb 1, 2012, at 2:13 PM, Brendan Eich wrote:
>>> >  Allen Wirfs-Brock wrote:
>>>> >>  Another loose end.
>>>> >>  >>  With the addition of for-of, for-in reverts back to always iterating over the property keys of an object as it does not support the generalized iteration protocols.  An implication of this is that using a de-structuring pattern as the iteration variable has very limited utility:
>>>> >>  >>      for (let [c] in obj) print(c);  //print the first character of
>>>> >>      each of obj's enumerable property names
>>>> >>  >>      for (const {length:len}  in obj) print(len);  print the length
>>>> >>      of each of obj's enumerable property names
>>>> >>  >>  >>  Given this lack of utility, why should we allow de-structuring in this context?
>>> >  >  These are not totally silly examples. I say when in doubt, let language regularity win.
>> 
>> Well, they're at least 98% silly and these were the only even semi-plausable example I could think of.
> 
> So you agree with my point about regularity + non-silly use-cases winning? :-/

I like regularity, which was why I was content to keep the 98+% silly initialization expression in for-in  |for (var k=debugLog("starting loop") in obj)...|. keeps it all together for refactoring :-\

But, in reality I was probably more concerned about the breaking change issue.
> 
> 
>>> >  We are also thereby future-friendly in case some evolution of property keys becomes even more structured. I know, unlikely, but again: regularity when in doubt.
>> 
>> In which case, it would be easy enough to allow them in the future. It's always easer to relax a restriction then it is to add one.
> 
> How would you restrict them? Splitting productions, or semantic restrictions? It matters, not just aesthetically but for implementation simplicity.

In this particular case I would probably use separate productions (already did that to eliminate the initializers for |for (let/const x in)|.  In general, I prefer to only use static semantic restrictions only when they involve non-nearby contextual information about the program.

However, that is a specification aesthetic.  I don't see why an implementation parser would necessarily want to make the same grammar trade-offs. Converting grammar to static checks and visa versa seems like very routine parser engineering.  
 
> 
> 
>> I don't really see the consistency in trying to ban the initializer in
>>   for (var k=42 in obj) ;
>> because it is a "awful, lazy-grammar-resue error".
> 
> ES1 was based on real implementations. The Netscape one did not allow an initaliser here. There's no good use for it compared to destructuring key lengths or substrings, especially not with var (which hoists). You want an initial var value to survive a zero-iteration loop? Hoist the var.
> 
>>   While adding
>>   for (var [c] in obj) ;
> 
> Are you really "adding"? It depends on good vs. bad reuse of sub-grammar. I appealed to regularity. That means standard rules for conjugating verbs, etc., in natural languages.

Well, its adding to the grammar I wrote this morning...
I already have to have  additional productions (or static semantic rules, they amount to the same thing) that don't have initializer expressions on the for (let/const forms.

But I like standard rules too.  Too many special cases make the language harder to learn.  But regularity that allow for WTF situations also isn't good.  There is a sweat spot that needs to be found.

> 
> In programming languages one would hope that binding forms would compose the same with for-in as for-of as for;; and other binding contexts, modulo the initialiser. At least, that's what users of JS1.7-and-up have hoped.
> 
> That evidence is tainted because we did make for-in programmable via an iteration protocol, as for-of is in ES6. Granted. But unless there's an actual hardship in regularity (I don't believe there is with for-in, but I welcome evidence from you on spec front, and other implementors on impl front) I still think regularity wins.

I actually think may two use cases for for-in de-structuring (as currently defined)  are pretty close to WTF scenarios.  Most people are going to have to stop and think carefully about what they mean.  Probably more important, allowing destructuing in for-in is likely to further confuse people regularly forget that it iterates over keys rather than values.
> 
>> I don't actually feel too strongly either way and it is actually more work for me to disallow the destructuring pattern.
> 
> I'm not super-strong on this, don't get me wrong. It's much less of an issue either way than banning the initialiser for let and const. I hope we agree on that much, as a partial order of preferences or strong convictions!
> 
> It also seems relevant that you'd have to do more work in the spec, and presumably make the grammar bigger, to disallow destructuring (with and without var/let/const) in for-in. More spec effort and grammar size make for errata habitat. Just as with code.

For (in all variations) has lots variation and a fair amount of complexity.  I these issues are on the fringes and really don't change the overall complexity very much one way or the other.  But they do need to be decided.

> 
> 
>>   However, I am trying to find some basis for consistency in the design choices we make.
> 
> Again, for-in as designed in JS1 never allowed an initialiser and it's an unwanted feature added to match JScript or (perhaps JScript too lacked it) to reuse part of the grammar a certain way.
water under the bridge...
> 
> Note that the reuse of VariableDeclarationNoIn didn't save anything in the grammar, so I bet the issue was JScript allowing an initialiser. Anyone know?
> 
> It's never inconsistent to allow one thing and disallow another. The particulars matter. This isn't "anything goes". Destructuring has a bit of utility and a lot of regularity in for-in head position. The initialiser from VariableDeclarationNoIn has neither specific utility nor regularity with respect to for-in in AWK, Python, or any other language with such a construct.
> 
> /be
> 



More information about the es-discuss mailing list