Day 2 meeting notes
brendan at mozilla.com
Fri Jul 30 16:37:01 PDT 2010
On Jul 30, 2010, at 3:53 PM, Faisal Vali wrote:
>> ---------- Forwarded message ----------
>> From: Douglas Crockford <douglas at crockford.com>
>> To: Oliver Hunt <oliver at apple.com>
>> Date: Fri, 30 Jul 2010 13:09:33 -0700
>> Subject: Re: Re: Day 2 meeting notes
>> On 11:59 AM, Oliver Hunt wrote:
>>> I keep seeing code like this, I simply don't see it as viable to have "for (.. in ...)" sometimes enumerate property names, and some times enumerate keys, it seems like it could be both confusing and error prone. esp. given the simplest example: [x for (value in [1,2,3])] you would not get the desired behaviour, unless in comprehensions for(in) behaves differently from everywhere else.
>>> It seems far better to just define a distinct syntax for enumerating values of an object.
>> I agree. We talked about swapping out the preposition, so for..in produces keys, and for..of or for..from produces values.
> What about using 'for .. vin' - i.e. value-in for value enumeration
> And adding a redundant 'for .. kin' - i.e. key-in for key enumeration
> (for those who prefer explicitness over using the ambiguously named
> 'for .. in' which would retain its original key iteration behavior)?
> Or are 'vin' and 'kin' too nonsensical to gain any acceptance?
Yes, they're too nonsensical. Sorry, but you asked (and answered ;-).
Let's avoid bikeshedding just yet. It's really not going to resolve any usability concerns, and the prior question of whether we should design for the longer term and the bigger picture, rather than just adding more syntax to mitigate the concern about old for-in code running an iterator unexpectedly, should be addressed first (if possible).
There is a usability problem, I think everyone agrees. It has several aspects:
1. for-in is underspecified and not interoperably implemented, yet it is useful and used in spite of this -- its syntax is sweet, and (at least in small-world / "my own" code settings), reliable if used with some care.
2. for-in on arrays enumerates keys, just as with other objects, but this is often not what users want or expect.
3. for-in walks up the prototype chain. This is independent of 1 and 2, in the sense that even if we specify enumeration interoperably and engines do it, and even with ES5's Object.defineProperty to control enumerability, often enough users just Do Not Want.
With Harmony building on ES5 strict mode by default and inevitably adding new syntax, therefore requiring opt-in versioning, we hope to fix at least (1), which may impose a migration tax on some web content that "works" cross-browser today. Here's some detail on how:
We experimented in Firefox 4 nightlies with a pure "snapshot" model, where at the start of the for-in loop, the direct object and its prototypes are enumerated, with shadowing, and the property names saved. We left out suppression of names deleted after the loop starts but before the loop would visit the name in the snapshot -- we let those names be visited. This broke too much, so we added delete suppression, but only for the direct object. This seems web-compatbile enough, pending new negative results.
TC39 favored the snapshot model at the May meeting. This week's meeting was where we Mozillans relayed the need for delete suppression, at least for the direct object. The use-case is the "iterate a worklist" one, but not with adding to the worklist, only deleting. It's not formally nice, but it is done (e.g. event listeners in library-created listener arrays or maps). We do not yet propose to standardize snapshot-with-direct-object-only-delete-suppression, BTW.
I suspect we can't afford the migration tax imposed by fixing (2) and (3) above, especially (2). It's hard to know without running the experiment at scale -- and then it's hard to change course.
Nevertheless, it is conceivable that one day, for-in will be significantly more usable under a future Edition.
I believe that making for-in meta-programmable increases the odds of that day arriving, without in practice creating proxy vs. non-proxy enumeration confusion, because it lets JS authors and not just TC39 (with a few ugly new and hardcoded contextual keywords) add their good ideas and run local experiments, using iterators provided in the future Edition or by their own libraries.
This worked for Python. Why not for JS?
More information about the es-discuss