On Nov 22, 2010, at 11:49 AM, Brendan Eich wrote:

> On Nov 22, 2010, at 11:14 AM, Oliver Hunt wrote:
> 
>> On Nov 22, 2010, at 2:08 AM, Tom Van Cutsem wrote:
>> 
>>> My arguments in favor of keeping the existing "for-in" syntax and making it 
>>> meta-programmable:
>>> 
>>> - Simplicity. Don't underestimate the complexity creep of introducing a new 
>>> looping construct. Many small changes add up quickly. Especially for 
>>> novices, having two looping constructs that are so similar will be terribly 
>>> confusing.
>> 
>> You're not saving the addition of a looping construct, in making for-in 
>> behave differently depending on what is on the right hand side of 'in' 
>> you're merely adding an additional looping that is not syntactically 
>> observable.
> 
> Is the additional aspect important enough to split syntax over?
> 
> If so, would you make the new form *only* work on proxies and throw given a 
> non-proxy on the right of "in"?
> 
> If not, why not?

Proxies need to have a way to work with for(in) which is the only reason I 
believe they should be allowed to have a trap for for(in) enumeration.  It's 
necessary if you ever want to have DOM objects like NodeList be defined in 
terms of proxies.

>>> - Keeping the existing syntax means that the tons of JS code already out 
>>> there can instantly become client-code to iterators. As Brendan noted: you 
>>> can use iterators to generate a stream of keys (strings) without confusing 
>>> clients.
>> 
>> And all existing standards compliant code can no longer rely on for in doing 
>> what it has done for years.  Suddently for in _behaviour_ may change based 
>> on the prototype chain.
> 
> That's true in Harmony, and as you noted on the list a while ago, also true 
> in ES5 strict. I decried too much migration tax but allowed we want to break 
> compatibility for important wins. Lexical scope all the way up is one such 
> proposed win, justifying removing the global object from the scope chain.
> 
> In my view, letting for-in be reformed by library authors is another case 
> where the migration tax is worth it.
> 
> Now, I need to ask whether you are making an absolute statement: Harmony must 
> be runtime as well as syntactically compatible with ES5 strict, i.e., a 
> superset language?

I'm not sure what relevance pure lexical scoping in harmony has to a discussion 
on the behaviour of for(in).  If we're saying that every new API and language 
feature being discussed for harmony will only be available in harmony, then yes 
harmony can do whatever it wants, but you've also caused me to lose any 
interest in implementing harmony at that point.  If every feature being 
discussed is only usable inside harmony code then the migration cost of 
individual features won't be relevant as it's a distinct language with no 
impact on ES.

>>> - Client code to proxies that emulate objects with lots of properties can 
>>> continue to use for-in. It just feels wrong that client code should change 
>>> because of pure implementation details of an object (i.e. whether it 
>>> eagerly or lazily generates its keys).
>> 
>> My understanding was that proxies would have a trap to allow them to 
>> generate an array of strings to be used.
> 
> That's true, the fundamental trap is enumerate, but as noted on the wiki and 
> pointed out by Waldemar when we reviewed proxies and moved them to 
> harmony:proposals status, this does not work well for "large" and "infinite" 
> objects.
> 
> We moved proxies to harmony:proposals status with the agreement that the 
> iteration protocol would address such hard cases. The iterators proposal does 
> that, including details about proxies as prototypes of other objects (you 
> don't want to switch to iterate if you start with enumeration -- you must 
> call the proxy handler's enumerate trap).
> 
> Last week we agreed toward the end of the meeting, with some lack of clarity 
> about *how* to do this, to recast for (x in y) as for (x : keys(y)) and allow 
> either enumerate or (if provided) iterate to be used to handle large/infinite 
> objects.
> 
> Now the for-: syntax looks like a mistake, and we still haven't reworked 
> things to address the required large/infinite cases.
I don't understand why : was a mistake, the only counter argument i saw was 
that it didn't work well with type annotations, which i see no value in and 
aren't being discussed for harmony or es-next.  Honestly I wish people would 
stop treating type annotations as something important -- ES is a dynamically 
typed language, trying to shoe-horn static typing in seems strange.

> I'm reviewing all this because I do not think everyone has kept up with the 
> details. But the details matter, and they have some irreducible complexity we 
> can't wish away. They motivate more than just the enumerate trap which 
> eagerly returns all the property keys
> 
> 
>>> Of course, if an object changes its behavior from iterating keys to 
>>> iterating values, this breaks clients and they should be modified to use 
>>> "for (var k in keys(obj))". But I don't see how this differs from any other 
>>> such changes made to an object. The important thing to note here is that 
>>> turning an object into an iterator requires explicit action by the 
>>> programmer. If iterators were implemented ala Python using a magical 
>>> "__iterate__" hook, then I'd complain because Harmony code could silently 
>>> turn normal objects into iterators. But there's no such risk with this 
>>> proposal.
>>> 
>>> I think that's a key point worth re-iterating: iterators and regular 
>>> objects are sufficiently distinct so that there's no risk of automatically 
>>> converting one into the other. There is only a risk to existing client-code 
>>> if a Harmony programmer changes a normal object into an iterator. But at 
>>> that point the programmer knows he's making a non-upwards-compatible change 
>>> and clients should be changed accordingly. I don't see how the for-in case 
>>> differs in this respect, fundamentally, from say, renaming a method.
> 
>> I do not expect the behaviour of for(in) to change from harmony to 
>> non-harmony code.  Ignoring all other concerns it would mean the behaviour 
>> of objects passed from a harmony context to a non-harmony context would be 
>> unexpected.
> 
> That is a risk but it is not an absolute. It is one end of a trade-off. The 
> other end is the benefit of avoiding new and hard-to-make-winning syntax, 
> splitting for-in and for-: by dynamic type of what is on the right-hand side 
> of in vs. :, complicating the surface language, and precluding library 
> authors from helping in the near term.
How do library authors help?  They can't add value enumeration of anything as 
that will break any existing code that uses for(in) over any of their objects.  
And given the desire that the library writers have to make their libraries 
paper over browser differences they're not going to introduce changes that 
completely change object behaviour from one engine to the next.

If there were a separate syntax, they could provide a custom iterator, and tell 
devs it was there, so devs would be able to use the nicer enumeration feature 
when they know that the syntax is available.

>> If this was going to be the outcome why did we even spend time discussing 
>> this?
> 
> Because we were trying to reach agreement. Who says failure is not an option? 
> Failure is important. It also is not permanent. Making this into a one side 
> must win and the other must lose game would be a mistake. The game is still 
> on, and there can be more winners than losers.
> 
> I said at the meeting that we couldn't prove someone wouldn't mix Harmony and 
> non-Harmony code and objects, and have non-Harmony code run for-in over a 
> proxy with an iterate trap, and find some kind of surprise.
> 
> This is the down side. It is not so obviously terrible and fatal that we all 
> agree to abandon meta-programmability of for-in. It's an unquantified risk, 
> probably small -- greater than the ES5 strict migration tax risks (eval of 
> var, arguments aliasing, caller/callee) and less than the Harmony lexical 
> scope all the way up (no global object on scope chain) risks, in my best 
> guess.
> 
> Suggestion: we make old for-in loops never run the proxy iterate trap. Only 
> for-in code that opts into Harmony (analogous to "use strict" changing 
> eval-of-var and arguments) gets the meta-programmability. What say you?

I don't believe harmony-only is reasonable, it would mean that for a developer 
to use just the new enumerator they would have to rewrite everything to deal 
with the now missing global object.  And once again, i think using "harmony" as 
a mode switch to change behaviour of things unrelated to lexical scoping is the 
wrong approach.

> 
> /be

_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to