Paren-Free (was: Re: Nov 18 notes)
http://brendaneich.com/2010/11/paren-free/ Fasten your seatbelts, it's going to be a bumpy night! /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
I'd like to contribute what I think are three not-yet-voiced arguments to this discussion: 1) Iterators != Collections First, let me briefly restate what I preceive to be the main point of contention: if we overload for-in, then client code that previously executed for (x in obj) with obj being a regular object, and now finds itself in Harmony-land where obj _is changed to_ an iterator, then for (x in obj) may confuse the client, if the iterator produces non-string values. Coming back to my point that regular objects don't just become iterator objects overnight: it was not yet emphasized that in Dave's iterators API, iterators are essentially considered as proxies for collections, usually even constructed for one-off iteration use only. That is: the original collection object itself is _not_ iterable, and that means that clients that hold on to just the collection object can never become for-in-confused. I feel that this tremendously reduces the risk of confusion, even though it is still possible, and I have no empirical evidence to back this up. However, reasoning by analogy: in pre 1.5 Java, one also asked a Collection for an Iterator, then iterated using the Iterator, not the original Collection. Of course, Java's static type system virtually rules out all confusion since Iterator is not a subtype of Collection, but I would argue that in this case, it was the _idiom_ more than the type system that avoided confusion. Java programmers didn't get confused because it was idiomatic to write: for (Iterator it = coll.iterator(); it.hasNext(); ) { ... it.next() ... } In Harmony, as Dave has shown, it would be idiomatic to use iterators as follows: for (var x in coll.iterator()) { ... } Note: if a harmony programmer would, in a stroke of forgetfulness, forget the .iterator() part, he'll get _the usual_ for-in enumeration behavior for 'coll', since 'coll' is a normal collection object, not an iterator. Of course, if the programmer meant to do iteration, this is a bug. But, more importantly, if the programmer wasn't forgetful and he meant what he wrote (i.e. enumerate the keys of the collection object), it'll do the right thing. If this is the idiom around which Harmony iterators are based, I would find it unlikely (drawing from my experience with Java Iterators) that Harmony programmers will start passing out references to coll.iterator() to clients where they meant to pass 'coll'. I would only expect to see .iterator() in or close to a for-in loop that immediately 'uses up' the iterator. 2) Avoid Iterators that pretend to be Collections Now, in light of the above, one reservation I have about Iterators is the API method called Iterator.for(coll), which creates and returns an iterator that is _also_ a forwarding proxy to coll. This method gives an incentive to users to pass this proxy where they could have also passed 'coll' to a client. I think this is a mistake. Iterators should be distinct from collections, as in Java. If iterators are indeed substitutable for collection objects, then the chance of confusing clients becomes much greater than it should be, effectively undermining argument 1) 3) Who is to blame for client confusion Andreas, in the thread on guard syntax, observed that there is a very thin line between a proxy enumerating duplicate/nonsensical keys (which is possible using just the enumerate() trap, and perhaps even necessary to emulate quirky host objects) and producing arbitrary values. Clients may get confused either way. It seems to me that we attribute different weights to these confusions based on the perceived use of proxies. Why is this? Here's my take on it: - proxies that use enumerate() to generate faux and/or duplicate keys are considered by us to somehow abuse the trap. We cannot prevent anyone from writing bad proxies, but we also don't expect code that does this to be idiomatic, or part of a popular library. Hence, even though these proxies may _deliberately_ confuse client code, we expect the consequences to be contained. It's obvious who to blame for the confusion in this case. - proxies that use iterate() to generate streams of arbitrary values are considered a legitimate use case. Under the hypothesis that strawman:iterators would become part of the language, it is our expectation that such proxies _will_ become widespread. When they do, client code that previously executed for (x in obj) might now find obj bound to an iterator and get confused. Hence, even though it wasn't the intention of the iterator proxy to confuse the client, the confusion happened anyway. This is considered more problematic, because it's hard to figure out who to blame. Both client and proxy meant to cooperate, but failed. In short: - Idiomatic use of iterators should prevent client code confusion in the common case. - Objects don't become iterators overnight. When porting ES5 code to Harmony, I would expect ES5 objects used as collections to now get an iterator() method that returns a
Re: Nov 18 notes
On Nov 22, 2010, at 11:35 PM, Brendan Eich wrote: On Nov 22, 2010, at 11:19 PM, Maciej Stachowiak wrote: Probably we need to take our time and not rush into a meta-programming-here syntax variant of for-in. I'll not propose anything better right now. If the colon is less future-compatible than we like, why not: foreach (var i in x) All the new words are not reserved, so they could begin a function call expression in extant code: hi = there foreach (i in x) print(i) means hi = there; foreach(i in x); print(i); today. Same if you s/foreach/iterate/ or any non-reserved identifier. Wherefore Allen's co-opting of enum (plus with, a decent preposition given enum but 8 chars in two keywords hurt kittens everywhere). One possibility is to add a space as apparently a few other languages do: for each (var i in x) Should be unambiguously parsable and easy to understand. Anyway, the bikeshed is secondary. We need to agree on what meta-programmable for-in means with the enumerate trap (specified by the wiki pages on harmony:proxies), how that changes with the optional iterate trap (strawman:iterators), and when it might matter (for all for-in loops, or only those in Harmony code?). Fair enough. Another important question is whether for..in should continue to guarantee that all values enumerated would be strings. Preserving that guarantee clearly makes for..in useless for the strawman:iterators purpose, but not for the harmony:proxies enumeration trap (and thus iterators would need new syntax to be usable). Breaking the guarantee may cause problems for existing code. Breaking the guarantee only in Harmony mode creates additional migration tax. Thus, iterators create a potential motive for new syntax that the proxy enumeration trap does not. Given this, it is useful to identify candidate syntax that doesn't have perceived showstopper problems, so that we can evaluate the tradeoffs among the three prongs of the trilemma. (As an even more concrete previously mentioned example, a new syntax allows sane defaults for arrays without breaking compatibility for the existing construct.) Regards, Maciej ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
On 2010-11-22, at 02:37, David Herman wrote: if we allowed for-in to be overloaded, I would tell people that they should deprecate the legacy for-in and replace it with an explicit iterator such as: for (x in keys(obj)) I have learned a mnemonic for for-in: that it is iterating using the `in` operator. You propose that I unlearn that? Or in your new hypothetical world does the `in` operator also get overloaded? Ramdom thought: Can I use destructuring in for-in? for ({key:value} in enumerable) for ([value] in iterable) ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
On Nov 23, 2010, at 12:11 AM, Maciej Stachowiak wrote: One possibility is to add a space as apparently a few other languages do: for each (var i in x) Should be unambiguously parsable and easy to understand. This is what ECMA-357, E4X, does, and it indeed iterates values not keys. The obvious criticism is that nothing except (dubious) history says for-in == keys while for-each-in == values. Other symmetries break down: for (i in o) assert(i in o) lacks this parallel construct: for each (v in o) assert(o[what-was-v's-name-again?] === v) JS1.7 allowed key-value destructuring for ([k, v] in o) assert(o[k] === v) // assume idemptotent has/get but this broke a different symmetry: for ([s, v, o] in tripledb) ... which wants other destructuring patterns to destructure the value returned by the iterator. Making the two-element-array destructuring pattern mean key-value destructuring frustrates people who want to iterate over a pairdb. So we fixed this in JS1.8, and dherman's iterator proposal has for (k in keys(o)) ... for (v in values(o)) ... for ([k, v] in properties(o)) ... EIBTI once again. Anyway, the bikeshed is secondary. We need to agree on what meta-programmable for-in means with the enumerate trap (specified by the wiki pages on harmony:proxies), how that changes with the optional iterate trap (strawman:iterators), and when it might matter (for all for-in loops, or only those in Harmony code?). Fair enough. Another important question is whether for..in should continue to guarantee that all values enumerated would be strings. Preserving that guarantee clearly makes for..in useless for the strawman:iterators purpose, Not quite, as Andreas already argued and (I see, reading ahead) reiterates with dherman adding emphasis. Stringifying is not good for iterating arbitrary values, in particular property values or key-value pairs, of course. But if you insist (I don't) that for-in always stringify, forever, there are still lazy use-cases for the proposed iterate trap. but not for the harmony:proxies enumeration trap (and thus iterators would need new syntax to be usable). Breaking the guarantee may cause problems for existing code. Breaking the guarantee only in Harmony mode creates additional migration tax. Thus, iterators create a potential motive for new syntax that the proxy enumeration trap does not. We're going in circles. Clearly, we could add new syntax. It's also conceivable that we could extend for-in. Trade-offs abound and data on usability hazards is absent in our experience (JS1.7 and up). Given this, it is useful to identify candidate syntax that doesn't have perceived showstopper problems, so that we can evaluate the tradeoffs among the three prongs of the trilemma. It's a problem if showstopper criteria are not shared in a committee. Then anyone can stop the show based on divergent principles or unarticulated beliefs. It therefore seems more important to achieve consensus on principles, and less important to force new syntax as a compromise that may be founded on bad committee game theory. (As an even more concrete previously mentioned example, a new syntax allows sane defaults for arrays without breaking compatibility for the existing construct.) Mozilla-specific JS hackers do use for each (v in a) ... to iterate values in an array |a|. This is better than for (i in a) { v = a[i]; ... } but it's not so much better that TC39 members are happy to adopt for-each-in from ECMA-357. Maybe we will, in the end. It is overlong and each is redundant or ambiguous (take your pick), but at this point it beats the rushed for-: ugliness of last week. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
On Nov 23, 2010, at 5:19 AM, P T Withington wrote: On 2010-11-22, at 02:37, David Herman wrote: if we allowed for-in to be overloaded, I would tell people that they should deprecate the legacy for-in and replace it with an explicit iterator such as: for (x in keys(obj)) I have learned a mnemonic for for-in: that it is iterating using the `in` operator. You propose that I unlearn that? Or in your new hypothetical world does the `in` operator also get overloaded? Excellent question. One (Java extension language) answer: http://www.cs.cornell.edu/Projects/jmatch/ Python allows unstratified meta-programming of both its for-in loop/comprehension syntax *and* its |in| operator. Harmony Proxies allow meta-programming of |in| already, via the |has| trap. So the answer to your quesiton does the `in` operator also get overloaded? is Yes, but you have to write two traps, iterate and has. Ramdom thought: Can I use destructuring in for-in? for ({key:value} in enumerable) for ([value] in iterable) Absolutely. Destructuring (separate proposal but composes well) applies to all LHS and binding forms. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
On Nov 23, 2010, at 11:12 AM, Brendan Eich wrote: Given this, it is useful to identify candidate syntax that doesn't have perceived showstopper problems, so that we can evaluate the tradeoffs among the three prongs of the trilemma. It's a problem if showstopper criteria are not shared in a committee. Then anyone can stop the show based on divergent principles or unarticulated beliefs. It therefore seems more important to achieve consensus on principles, and less important to force new syntax as a compromise that may be founded on bad committee game theory. The principle could be refined from Dave's restatement of Allen's (1a): 1a'. If existing syntax is given new semantics, it should extend the existing semantics conservatively. Otherwise, the new semantics should get new syntax. But conservatively needs defining. I think rather than try to nail down an abstract principle, we should look at the particular things in themselves. Tom's post did this: 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. [https://mail.mozilla.org/pipermail/es-discuss/2010-November/012208.html] This is an argument about APIs. If an object exposed by an API, say returned from an API function, was a plain old object with keys to enumerate, but now (with Harmony implementations targeted) returns a proxy with an iterate trap, *and* the iterator returns non-strings non-keys (but key is ill-defined if not string), then client code *could* break. But this is an intentional API change. It is analogous to renaming a method, and plausibly, object detection if not renaming would be used to deal with downrev clients. What about unintended consequences? An accidental proxy leak from Harmony code to pre-Harmony code is possible. This is why I raised the idea of runtime semantics under Harmony opt-in being required to meta-program for-in. The same opt-in is required to remove the global object from the scope chain in favor of a lexical top frame. We can (and have!) argue about limits on migration taxation, implementor burdens, etc. But as ES5 strict changed runtime semantics, it seems Harmony will too (lexical scope). So it is not absolutely inconceivable, or even obviously wrong, that for-in might become metaprogrammable based on its static code in Harmony property. (As an even more concrete previously mentioned example, a new syntax allows sane defaults for arrays without breaking compatibility for the existing construct.) Mozilla-specific JS hackers do use for each (v in a) ... to iterate values in an array |a|. This is better than for (i in a) { v = a[i]; ... } but it's not so much better that TC39 members are happy to adopt for-each-in from ECMA-357. Maybe we will, in the end. It is overlong and each is redundant or ambiguous (take your pick), but at this point it beats the rushed for-: ugliness of last week. Lest anyone think I'm throwing in the towel -- I'm not. We need better principles and detailed arguments justifying them or we won't have lasting and sound consensus to do much of anything with the language. Proxies moved to harmony:proposals status because they were designed carefully, very well specified, and prototype implemented (and the prototyping was essential to completing the spec and getting the design right). On one point of contention in the July meeting, I urged TC39 to let the champions of the proposal (Mark and Tom), decide what to do. I'd like to continue this champion-decides approach. Committees are terrible at designing, specifying, and implementing. It would be much better if we had multiple Proxy implementations (one for v8 is on github, Tom noted recently: https://github.com/brickysam26/node-proxy), including the iterate trap as proposed, and then some early adopters using proxies and beating on the iteration protocol. At that point we would have more information on the usability issues. In the mean time, we can try to refine our principles based on concrete analysis. Just making abstract never do X rules won't cut it. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
On 2010-11-23, at 14:14, Brendan Eich wrote: On Nov 23, 2010, at 5:19 AM, P T Withington wrote: On 2010-11-22, at 02:37, David Herman wrote: if we allowed for-in to be overloaded, I would tell people that they should deprecate the legacy for-in and replace it with an explicit iterator such as: for (x in keys(obj)) I have learned a mnemonic for for-in: that it is iterating using the `in` operator. You propose that I unlearn that? Or in your new hypothetical world does the `in` operator also get overloaded? Excellent question. One (Java extension language) answer: http://www.cs.cornell.edu/Projects/jmatch/ Python allows unstratified meta-programming of both its for-in loop/comprehension syntax *and* its |in| operator. Harmony Proxies allow meta-programming of |in| already, via the |has| trap. So the answer to your quesiton does the `in` operator also get overloaded? is Yes, but you have to write two traps, iterate and has. How does the `in` in for-in decide which of it's overloaded meanings applies? Based on the type of the operand? Based on the existence of the enumerate or iterate trap on the operand? And despite the `in` in for-in either enumerating or iterating, the `in` operator only has a single associated trap. The non-parallelism is bugging me. Ramdom thought: Can I use destructuring in for-in? for ({key:value} in enumerable) for ([value] in iterable) Absolutely. Destructuring (separate proposal but composes well) applies to all LHS and binding forms. I was being too subtle. I was suggesting something like your JS 1.7 example, where the 'top-level' destructuring is a pattern for the `in` operation. `{key: value}` means I want the property keys and their values, `[value]` means I want the values, and `key` is (backward-compatible) shorthand for `{key: _}`. Destructuring iteration over an hash of triples: for ({key: [s, v, o]} in tripledb) ... Too cute? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
On 11/23/10 11:12, Brendan Eich wrote: for (k in keys(o)) ... for (v in values(o)) ... for ([k, v] in properties(o)) ... What are keys, values, and properties here? Global functions? How would a new object abstraction T customize them just for instances of T? Waldemar ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
for (k in keys(o)) ... for (v in values(o)) ... for ([k, v] in properties(o)) ... What are keys, values, and properties here? Global functions? Those are API's suggested in the strawman:iterators proposal. They would be importable from a standard module. How would a new object abstraction T customize them just for instances of T? By writing its own custom iteration protocol via proxies with the iterate() trap implemented appropriately. E.g.: function MyCollection() { } MyCollection.prototype = { iterator: function() { var self = this; return Proxy.create({ iterate: function() { ... self ... }, ... }); } } Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
On Nov 23, 2010, at 12:14 PM, P T Withington wrote: Harmony Proxies allow meta-programming of |in| already, via the |has| trap. So the answer to your quesiton does the `in` operator also get overloaded? is Yes, but you have to write two traps, iterate and has. How does the `in` in for-in decide which of it's overloaded meanings applies? Based on the type of the operand? Based on the existence of the enumerate or iterate trap on the operand? A proxy's handler is a single object with trap methods. These traps work together to create an abstraction. It should be a coherent abstraction (ideally, don't you think? ;-). If you're implementing an iterator, then the iterate and has traps are enough to make for-in and in agree. From Python experience, just iterate is enough. (JMatch is cute because it can synthesize both iteration and membership testing from Boolean formulae, but we're not going to try for anything like it.) If you're implementing a container, then questions of mutability arise. Immutable container proxies could have iterate, has, and get. Mutable containers might rather vend iterators via specific API methods, where the iterators are separate proxies that iterate over snapshots. There are lots of possibilities. And despite the `in` in for-in either enumerating or iterating, the `in` operator only has a single associated trap. The non-parallelism is bugging me. There are at least two reasons for this: 1. Large and lazy objects cannot afford to enumerate all keys eagerly, as the enumerate trap wants. 2. in maps to the has trap, which must eagerly compute a boolean result. With just harmony:proxies as proposed, (1) motivates adding a derived trap, call it iterate, that can be used instead of enumerate. This is the proposed solution to the large/lazy object problem that we agreed to fix when moving Proxies to harmony:proposals status. Notice how in does not have a large/lazy problem. Membership queries must be answered eagerly, all at once, with a boolean result. This is (2). Another reason (3) is to support iterators as a special kind of proxy. All objects can be enumerated if not iterated, but not all objects are iterators. Adding a derived, lazy-iteration trap to use instead of enumerate allows proxies to implement iterators for arbitrary value streams. This is something we propose separately from proxies, but build on proxies (rather than reinventing obvious wheels). We thus handle large/lazy object enumeration (string typed key streams) as well as custom iterateion (arbitrarily typed value streams). The particulars matter. Tom invokes Einstein's famous as simple as possible, but not simpler dictum in his talks on proxies. Both JS's particulars, and hard realities to-do with scaling to large or lazily built objects, motivate non-parallel trap structure here. Trying to oversimplify will just make an unusably simplistic metaprogramming API that falls down on some use-cases, or too easily leads to incoherent abstractions. Ramdom thought: Can I use destructuring in for-in? for ({key:value} in enumerable) for ([value] in iterable) Absolutely. Destructuring (separate proposal but composes well) applies to all LHS and binding forms. I was being too subtle. I was suggesting something like your JS 1.7 example, where the 'top-level' destructuring is a pattern for the `in` operation. `{key: value}` means I want the property keys and their values, No, that destructuring pattern {key: value} captures only the key property's value, bound to the name value on each turn of the loop. Making it a special form just breaks destructuring for no good reason. `[value]` means I want the values, No, that means get the 0 property of the iterated value and bind it to the name value. http://wiki.ecmascript.org/doku.php?id=harmony:destructuring and `key` is (backward-compatible) shorthand for `{key: _}`. Destructuring iteration over an hash of triples: for ({key: [s, v, o]} in tripledb) ... Too cute? Too restrictive and verbose, also does violence to destructuring by reinterpreting its syntax. Destructuring lets you pull properties from objects using object and array patterns modeled on initialisers, in a way that honestly desugars to property references and assignments. Iteration (whatever the syntax) lets you visit a sequence of values, whatever their type and deeper structure. Destructuring the iterated value conveniently binds values from the deeper structure to names or local variables declared in the iteration's loop syntax and used in the loop body. Thus there is no good reason to hardcode key as a name, or any particular one- or two-property pattern, in order to deal with objects as key/value stores using destructuring and iteration. We can leave destructuring unaltered and provide different iterators for the key, value, and key-value (and triple, quad, etc.) use cases. As dherman noted, iteration
Re: Nov 18 notes
How would a new object abstraction T customize them just for instances of T? By writing its own custom iteration protocol via proxies with the iterate() trap implemented appropriately. E.g.: function MyCollection() { } MyCollection.prototype = { iterator: function() { var self = this; return Proxy.create({ iterate: function() { ... self ... }, ... }); } } I left out the last step: clients would then use this via: var coll = new MyCollection(); ... for (var x in coll.iterator()) { ... } Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
On Nov 23, 2010, at 1:05 PM, Brendan Eich wrote: If you're implementing a container, then questions of mutability arise. Immutable container proxies could have iterate, has, and get. Mutable containers might rather vend iterators via specific API methods, where the iterators are separate proxies that iterate over snapshots. There are lots of possibilities. For some reason I typed container where I meant collection -- could be that both terms work, but collection is better. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
On 11/23/10 13:05, David Herman wrote: How would a new object abstraction T customize them just for instances of T? By writing its own custom iteration protocol via proxies with the iterate() trap implemented appropriately. E.g.: function MyCollection() { } MyCollection.prototype = { iterator: function() { var self = this; return Proxy.create({ iterate: function() { ... self ... }, ... }); } } I left out the last step: clients would then use this via: var coll = new MyCollection(); ... for (var x in coll.iterator()) { ... } Dave That misses the point of my question. Sure you can define the meaning of for (k in MyNewFunction(o)) or for (k in o.MyMethod()) However, I asked how a new object abstraction T would customize keys, values, and properties just for instances of T so that instances of T could be usable under the standard pattern: for (k in keys(o)) ... for (v in values(o)) ... for ([k, v] in properties(o)) ... Waldemar ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
On Mon, Nov 22, 2010 at 8:37 AM, David Herman dher...@mozilla.com wrote: for (var i : x) ... // must be new iteration for (var i : T : x) ... // iteration again, but parsed how? for (var i : T in x) ... // for-in with annotated var Bummer! I'm beginning to feel more strongly again that overloading for-in, as opposed to introducing yet another syntactic variant of `for', is the right way to go. thought experiment Imagine we made Harmony backwards-incompatible in the following way: for-in loops would *only* work on iterable objects, and would dynamically fail on non-iterable objects. So if you wanted the legacy keys behavior, you would have to explicitly call a `keys' library function. /thought experiment If we're gonna go invent new keywords why not use the obvious? iterate (var x in y) ... ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
On Nov 22, 2010, at 12:49 AM, Peter van der Zee wrote: On Mon, Nov 22, 2010 at 8:37 AM, David Herman dher...@mozilla.com wrote: for (var i : x) ... // must be new iteration for (var i : T : x) ... // iteration again, but parsed how? for (var i : T in x) ... // for-in with annotated var Bummer! I'm beginning to feel more strongly again that overloading for-in, as opposed to introducing yet another syntactic variant of `for', is the right way to go. thought experiment Imagine we made Harmony backwards-incompatible in the following way: for-in loops would *only* work on iterable objects, and would dynamically fail on non-iterable objects. So if you wanted the legacy keys behavior, you would have to explicitly call a `keys' library function. /thought experiment If we're gonna go invent new keywords why not use the obvious? iterate (var x in y) ... Did you read Dave's previous post, or mine? We are not going to go invent some new overlong non-reserved word. for is the right word. One might try retasking do but it's ambiguous: do-while loops do not require braces (KR style favors them even for one-liners but it's just a convention). Dave's point about getting people to use one universal quantifying loop structure is good. If that loop syntax is not for-in, it will have to be something new that works even when there is no iterate trapping proxy. But that will just be a suckier version of the universal (enumerating if not custom-iterating) for-in from JS1.7. So what good are we really doing by forking for-in into bastard children (the one we have, definitely a bastard -- I should know! :-/) and a new one with red hair? /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
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. - 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. - 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). 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. Cheers, Tom 2010/11/22 Brendan Eich bren...@mozilla.com On Nov 22, 2010, at 12:49 AM, Peter van der Zee wrote: On Mon, Nov 22, 2010 at 8:37 AM, David Herman dher...@mozilla.com wrote: for (var i : x) ... // must be new iteration for (var i : T : x) ... // iteration again, but parsed how? for (var i : T in x) ... // for-in with annotated var Bummer! I'm beginning to feel more strongly again that overloading for-in, as opposed to introducing yet another syntactic variant of `for', is the right way to go. thought experiment Imagine we made Harmony backwards-incompatible in the following way: for-in loops would *only* work on iterable objects, and would dynamically fail on non-iterable objects. So if you wanted the legacy keys behavior, you would have to explicitly call a `keys' library function. /thought experiment If we're gonna go invent new keywords why not use the obvious? iterate (var x in y) ... Did you read Dave's previous post, or mine? We are not going to go invent some new overlong non-reserved word. for is the right word. One might try retasking do but it's ambiguous: do-while loops do not require braces (KR style favors them even for one-liners but it's just a convention). Dave's point about getting people to use one universal quantifying loop structure is good. If that loop syntax is not for-in, it will have to be something new that works even when there is no iterate trapping proxy. But that will just be a suckier version of the universal (enumerating if not custom-iterating) for-in from JS1.7. So what good are we really doing by forking for-in into bastard children (the one we have, definitely a bastard -- I should know! :-/) and a new one with red hair? /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
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. - 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. - 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. 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. I'm kind of frustrated that after discussing all this last week, and apparently getting to some kind of consensus, we've more or less instantly gone back to what we had at the beginning of the meeting, where for(in) gets magically overloaded and a developer has some magical way to understand what a given for(in) loop is going to do. If this was going to be the outcome why did we even spend time discussing this? --Oliver ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
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? - 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? - 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'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,
Re: Nov 18 notes
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
Re: Nov 18 notes
On Nov 22, 2010, at 12:09 PM, Oliver Hunt wrote: 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. Yes, that's already in the harmony:proxies design via the enumerate trap. You didn't answer my questions, though. If we were to add for (x : y) as you among others seemed to want last week, would it throw on a non-proxy on the right of :? The answer matters both so we can hope to define for-: (whatever its syntax, if not for-in), and so we can reach agreement on premises. One premise: new users of Harmony implementations can just always use for-: as dherman said. They never have to use for-in. For enumeration, they use for (k in keys(o)). Agree or disagree? If you are indifferent then you're not really participating :-/. - 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). It's a breaking change to the language's runtime semantics, but not to any syntax. It seems entirely analogous to the case of migrating for-in code from pre-Harmony into Harmony, and as I guessed last time, losing the global object looks strictly riskier in terms of unintended global property aliasing breakage. 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, We are not saying that because we do not want gratuitous differences for users or implementors. This is pretty clear from all our work. If we really wanted a totally new language, not only would it make for roughly 2x the learning curve for users, and lots of confused-mode bugs, it would make implementors do a bunch more work, approaching 2x. And as I also argued last week, TC39 would never pull it off. It would be design by committee and it would fail. So (in case this isn't obvious; I thought it was), we are trying to extend ES5 strict mode with only a few well-chosen runtime semantic shifts. Possibly few will be one: the global object removal in favor of lexical scope. New syntax brings new semantics of course. but you've also caused me to lose any interest in implementing harmony at that point. That's a straw man of your own devising, and I just knocked it down. Can we please get back to the crucial issues? 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. There's still a migration tax in porting from old to new language, however similar they are. You yourself raised this re: ES5 strict, which changes runtime semantics without any syntactic change (eval-of-var, arguments). It is the same point I'm making about lexical scope removing the global object. I hope it is clear now, both as a risk and an opportunity!
Re: Nov 18 notes
On Nov 22, 2010, at 12:39 PM, Brendan Eich wrote: On Nov 22, 2010, at 12:09 PM, Oliver Hunt wrote: 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. As Tom pointed out (re-read his message :-|), they can make enumeration work for large/lazy/infinite objects. No non-string non-keys required. The important point here is that for-in won't choke old browsers. New library code in the near term (when Harmony and pre-Harmony impls are in the field), assuming we let for-in be metaprogrammed in Harmony, can object-detect and meta-program for-in, and client *and* library code can use for-in and it will fail soft or fall back by other means. Not so if we add new syntax (for-: or anything old browsers will choke on). /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
On Nov 22, 2010, at 11:49 AM, Brendan Eich wrote: On Nov 22, 2010, at 11:14 AM, Oliver Hunt wrote: 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, I think I misread your based on the prototype chain words. I was making the general case for runtime semantic fixes -- few and worth making -- in Harmony as in ES5 strict. But I think you were supposing a proxy on a non-proxy's prototype chain could start returning non-string non-keys via its iterate trap. Not so. Here's a session with a fresh js shell (Firefox 4 latest code): js var proxy = Proxy.create({ has: function () { return false; }, enumerate: function () { return [a, b, c]; }, iterate: function () { for (let i = 0; i 10; i++) yield i; } }); js js var obj = Object.create(proxy); js js for (var i in proxy) print(i); 0 1 2 3 4 5 6 7 8 9 js js for (var i in obj) print(i); a b c Once for-in starts up a non-proxy object's prototype chain, only enumerate traps -- never iterate. And enumerate is fundamental, so if missing, the for in fails: js var proxy = Proxy.create({ has: function () { return false; }, iterate: function () { for (let i = 0; i 10; i++) yield i; } }); js js var obj = Object.create(proxy); js js for (var i in proxy) print(i); 0 1 2 3 4 5 6 7 8 9 js js for (var i in obj) print(i); typein:11: TypeError: enumerate is not a function /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
Rather than adding additional confusion by trying to comment on snippets from this thread, I think I'll just state my current opinions on the subject and the principles that they are based upon: 1a) New semantics should use new syntax in a manner that clearly avoids confusion with existing syntax. 1b) Syntax should generally be suggestive of a reasonable interpretation of the semantic 1c) Harmony is not being designed using the no new syntax rule 1d) There is nothing sacred about for as the initial keyword of an enumeration statement. From these I conclude that new iteration semantics should be syntactically distinct from the current for-in and probably the greater the syntactic distance from for-in the better. Following these principles, here is a suggestion for a new enumeration statement that makes use of existing reserved words: enum key with keys(x) { alert(key) } enum val with values(x) { alert(val) } enum [key, val] with properties(x) { alert(x. + key + = + val); } Since this is a new form, it can impose new syntactic conventions. For example, it always creates new bindings in the block that it iterates. An explicit var or let keyword is not needed. Also with has much broader semantic implications than in 2) Whenever possible, less general pre-existing syntactic forms should be redefined to desugar into new more general forms. ES1-5 for-in can be defined via desugaring to enum-with, for example: //desugar: for (var x in foo) {alert(foo[x])} var x; enum __x with __ES5forinEnumerator(x) { x=__x; {alert(foo[x])} } 3) Proxy traps should be defined based upon the new, more general semantics not legacy less general semantics. Define the traps necessary to support enum-with and depend upon the desugaring to take care of legacy for-in. 4) Provide builtin-library alternatives for new statements that can be used without down-rev syntax errors: Iterator.prototype.enumWith = function (func) { enum each with this { func(each) } } keys(x).enumWith(function(key){alert(key)}); values(x).enumWith(function(val){alert(val)}); properties(x).enumWith(function([key,val]){alert(x. + key + = + val)}); Leave it to library writers as to whether or not down-rev libraries are actually implemented. -Original Message- From: Brendan Eich Sent: Monday, November 22, 2010 12:48 PM To: Oliver Hunt Cc: es-discuss Subject: Re: Nov 18 notes On Nov 22, 2010, at 12:39 PM, Brendan Eich wrote: On Nov 22, 2010, at 12:09 PM, Oliver Hunt wrote: 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. As Tom pointed out (re-read his message :-|), they can make enumeration work for large/lazy/infinite objects. No non-string non-keys required. The important point here is that for-in won't choke old browsers. New library code in the near term (when Harmony and pre-Harmony impls are in the field), assuming we let for-in be metaprogrammed in Harmony, can object-detect and meta-program for-in, and client *and* library code can use for-in and it will fail soft or fall back by other means. Not so if we add new syntax (for-: or anything old browsers will choke on). /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
1a) New semantics should use new syntax in a manner that clearly avoids confusion with existing syntax. 1b) Syntax should generally be suggestive of a reasonable interpretation of the semantic 1c) Harmony is not being designed using the no new syntax rule 1d) There is nothing sacred about for as the initial keyword of an enumeration statement. Nobody said sacred -- I'm not genuflecting. :) Seriously, the reason for using for is that it's one of the most stable, common, and universally-used keywords for iteration in almost all languages. Introducing a new initial keyword is straying really far from precedent, both in JS and other imperative languages. But I appreciate your spelled-out premises. I think my main quibble is with 1a as a rule. I might prefer something like: 2a) If existing syntax is given new semantics, it should extend the existing semantics conservatively. Otherwise, the new semantics should get new syntax. From these I conclude that new iteration semantics should be syntactically distinct from the current for-in and probably the greater the syntactic distance from for-in the better. Following these principles, here is a suggestion for a new enumeration statement that makes use of existing reserved words: enum key with keys(x) { alert(key) } This is clever, but it just seems to go off the deep end: the syntax is too inconsistent with JS precedent. Also, enum is the wrong keyword -- in JS parlance, this is iteration not enumeration. I guess I'm still open to new syntaxes, but I also still feel that when you step back and weigh the trade-offs, the cost of all this new syntax is incommensurate with the amount of new semantics, and moreover the traditional for-in syntax is still the sweetest I've seen for custom iteration. I would rather extend the best syntax and leave the legacy special case as a very small wart than have a warty syntax with a supremely orthogonal semantics. 2) Whenever possible, less general pre-existing syntactic forms should be redefined to desugar into new more general forms. I think this is pretty uncontroversial; whatever syntax we decide on, the specific legacy construct can be defined in terms of the more general new construct. 3) Proxy traps should be defined based upon the new, more general semantics not legacy less general semantics. Define the traps necessary to support enum-with and depend upon the desugaring to take care of legacy for-in. You don't think for-in should even allow the enumerate trap? This seems to go against the design approach of proxies; it's not just for introducing new meta-programmable constructs, but also for meta-programming existing facilities. 4) Provide builtin-library alternatives for new statements that can be used without down-rev syntax errors: This seems like a good idea. Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
2a) If existing syntax is given new semantics, it should extend the existing semantics conservatively. Otherwise, the new semantics should get new syntax. Perhaps I should have numbered that 1a'). :) Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
On Nov 22, 2010, at 3:17 PM, Allen Wirfs-Brock wrote: Rather than adding additional confusion by trying to comment on snippets from this thread, I think I'll just state my current opinions on the subject and the principles that they are based upon: 1a) New semantics should use new syntax in a manner that clearly avoids confusion with existing syntax. 1b) Syntax should generally be suggestive of a reasonable interpretation of the semantic 1c) Harmony is not being designed using the no new syntax rule 1d) There is nothing sacred about for as the initial keyword of an enumeration statement. I will echo Dave in saying thanks for spelling out principles. Also that sacred is a bit one-sided -- I do not think your (1a) is sacred either. Are we even? :-| The forest-for-the-trees meta-point is that if we conservatively add new syntax when meta-programming existing would have gone over without incident, we've made the language irrevocably bigger. We can't ever take back the new syntax or get rid of the old. We will have a long wait switching developers over to the new, which has ripple effects as Tom's post pointed out. But no need to beat that drum again, I will stifle. From these I conclude that new iteration semantics should be syntactically distinct from the current for-in and probably the greater the syntactic distance from for-in the better. Following these principles, here is a suggestion for a new enumeration statement that makes use of existing reserved words: enum key with keys(x) { This is a clever homage to with :-P. The parenthesis-free head is unusual and invites Go-like innovation elsewhere: will Harmony drop mandatory parens around if, while, etc. heads? Iteration is not numbering or naming, so taking enum for this purpose promulgates a misnomer *and* precludes us using enum for a categorical sum declaration of some sort. 2) Whenever possible, less general pre-existing syntactic forms should be redefined to desugar into new more general forms. ES1-5 for-in can be defined via desugaring to enum-with, for example: //desugar: for (var x in foo) {alert(foo[x])} var x; enum __x with __ES5forinEnumerator(x) { x=__x; {alert(foo[x])} } This goes against the Proxy design. A proxy shouldn't have to special case __ES5forinEnumerator to customize for-in as opposed to enum-with, and customizing for-in should not affect enum-with when up the proto chain as one of my recent posts showed with a js shell session. If we must have new syntax to get customized iteration through TC39, we can spend way too much time coming up with acceptable syntax. But before we dive into that fun timekilling process, let's be really sure we are not missing the forest for the trees. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
-Original Message- From: David Herman Sent: Monday, November 22, 2010 3:55 PM To: Allen Wirfs-Brock Cc: Brendan Eich ; Oliver Hunt ; es-discuss Subject: Re: Nov 18 notes 1a) New semantics should use new syntax in a manner that clearly avoids confusion with existing syntax. 1b) Syntax should generally be suggestive of a reasonable interpretation of the semantic 1c) Harmony is not being designed using the no new syntax rule 1d) There is nothing sacred about for as the initial keyword of an enumeration statement. Nobody said sacred -- I'm not genuflecting. :) Seriously, the reason for using for is that it's one of the most stable, common, and universally-used keywords for iteration in almost all languages. Introducing a new initial keyword is straying really far from precedent, both in JS and other imperative languages. AWB: Perhaps I should have been a bit more general in 1d and said something like: respect precedent, except when it gets in the way. Precedent can mislead users as easily as it can help help them. One think I suspect that we have all observed (and probably experience) is the experienced programmers who starts trying to write JavaScript programmers using invalid assumptions based upon their experience with other languages. But I appreciate your spelled-out premises. I think my main quibble is with 1a as a rule. I might prefer something like: 2a) If existing syntax is given new semantics, it should extend the existing semantics conservatively. Otherwise, the new semantics should get new syntax. AWB: Thanks, I like that. Trying to articulate some principles was the main point. I felt the thread was feeling like it getting hung up on unstated and/or unshared prinicples. From these I conclude that new iteration semantics should be syntactically distinct from the current for-in and probably the greater the syntactic distance from for-in the better. Following these principles, here is a suggestion for a new enumeration statement that makes use of existing reserved words: enum key with keys(x) { alert(key) } This is clever, but it just seems to go off the deep end: the syntax is too inconsistent with JS precedent. Also, enum is the wrong keyword -- in JS parlance, this is iteration not enumeration. AWB: This was mainly a first cut trying to look at the problem from a slightly different angle but starting by only using the currently available set of reserved words. Other syntactic issues like usage of parenthesis could tweaked and in the end wouldn't seem particularly inconsistent with the syntax conventions for C-like languages. I agree that we have generally called this semantics iteration rather than enumeration, but I was working from out available set of reserved words and enum seems like the closest fit. I suspect that the majority of Javascript programmers couldn't really articulate the difference between enumeration and iteration (over). They will use whatever meaning we feed them via the language design. Of course, we should be consistent in our terminology and if we went this route we might want to adjust other uses of these terms. Also, it there are JS 1.8 precedent issues--I'm just not sure whether that usage is broad enough to matter that much. I guess I'm still open to new syntaxes, but I also still feel that when you step back and weigh the trade-offs, the cost of all this new syntax is incommensurate with the amount of new semantics, and moreover the traditional for-in syntax is still the sweetest I've seen for custom iteration. I would rather extend the best syntax and leave the legacy special case as a very small wart than have a warty syntax with a supremely orthogonal semantics. AWB: I worry that it is hard for people to learn when the same name is applied to different concepts. We already have two forms of the for statement that people have to learn. Further complicating it feels like it would be a pedagogical nightmare. 2) Whenever possible, less general pre-existing syntactic forms should be redefined to desugar into new more general forms. I think this is pretty uncontroversial; whatever syntax we decide on, the specific legacy construct can be defined in terms of the more general new construct. 3) Proxy traps should be defined based upon the new, more general semantics not legacy less general semantics. Define the traps necessary to support enum-with and depend upon the desugaring to take care of legacy for-in. You don't think for-in should even allow the enumerate trap? This seems to go against the design approach of proxies; it's not just for introducing new meta-programmable constructs, but also for meta-programming existing facilities. I haven't really studied the specific Proxy traps in detail. However, if we had a more generate iterate trap(s) that semantically subsumes the enumerate trap when used with appropriate desugaring, why would we need
Re: Nov 18 notes
-Original Message- From: Brendan Eich Sent: Monday, November 22, 2010 4:10 PM To: Allen Wirfs-Brock Cc: Oliver Hunt ; es-discuss Subject: Re: Nov 18 notes On Nov 22, 2010, at 3:17 PM, Allen Wirfs-Brock wrote: ... enum key with keys(x) { This is a clever homage to with :-P. AWB: actually, when I made this up I was a bit concerned using with because of its heritage. I got over it... The parenthesis-free head is unusual and invites Go-like innovation elsewhere: will Harmony drop mandatory parens around if, while, etc. heads? AWB: Since what comes immediately after enum is a declaration from there isn't any precedent for parens there. They could be added after the with if that felt more familiar. Iteration is not numbering or naming, so taking enum for this purpose promulgates a misnomer *and* precludes us using enum for a categorical sum declaration of some sort. AWB: See my reply to Dave Herman on this issue. 2) Whenever possible, less general pre-existing syntactic forms should be redefined to desugar into new more general forms. ES1-5 for-in can be defined via desugaring to enum-with, for example: //desugar: for (var x in foo) {alert(foo[x])} var x; enum __x with __ES5forinEnumerator(x) { x=__x; {alert(foo[x])} } This goes against the Proxy design. A proxy shouldn't have to special case __ES5forinEnumerator to customize for-in as opposed to enum-with, and customizing for-in should not affect enum-with when up the proto chain as one of my recent posts showed with a js shell session. AWB: Perhaps and we have other use cases of property name enumeration (Object.key and getOwnPropertyNames, the in operator) that may need the enumerate trap. I know that trap design was one of the starting points of this discussion so I probably should look more closely at this. If we must have new syntax to get customized iteration through TC39, we can spend way too much time coming up with acceptable syntax. But before we dive into that fun timekilling process, let's be really sure we are not missing the forest for the trees. AWB: For what it's worth, in the Northwest we have a long tradition of cutting down trees and then latter realizing that we don't have a forest any more... /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
On Nov 22, 2010, at 5:39 PM, Allen Wirfs-Brock wrote: AWB: Thanks, I like that. Trying to articulate some principles was the main point. I felt the thread was feeling like it getting hung up on unstated and/or unshared prinicples. I agree, and I try to make mine clear (let me know where I fail). It's important not only for reaching agreement (backing up and trying a different deductive path forward) but also in rejecting bogus premises, or reprioritizing. AWB: I worry that it is hard for people to learn when the same name is applied to different concepts. We already have two forms of the for statement that people have to learn. The C-based for(;;) loop is not really relevant in my experience. JS hackers use it (more below on why they might rather not), but they always distinguish it from for-in. Some good fraction of JS hackers know Python, where for-in has enumeration like behavior on dictionaries (just like JS objects), but value iteration on lists. The most frequent (in my hearing) unsatisfied expectation of users of for-in is not that it is a second form after the C-based for(;;) -- there's no mention of for(;;). Rather, it is that for (v in [1,2,3]) fails to iterate 1,2,3, instead enumerating 0,1,2. We can't satisfy this Pythonic expectation directly, but with meta-programmable for-in, users and library authors can help themselves, using keys, values, and other iterator factory functions. Further complicating it feels like it would be a pedagogical nightmare. I think this is exaggerated -- there's really no relation to for(;;), and the first-year students move up and on. The nightmare of unprogrammable for-in, if I may use that word, is both the non-interoperable mess of for-in today in ES3-ES5-level browsers, plus the enumerate trap of tomorrow -- never mind an iterate trap. But most programmers do not need to know about proxies. So weigh the nightmares by how many students reach JS grad school, where they learn about proxies at all. And give some weight to middling students of the future libraries, who will be able to for-in over array and other array-like objects' values. The C-style for (var i=0; i a.length; i++) { var v = a[i]; ... } alternative-nightmare would be vanquished by the dawn of for (var v in values(a)) { ... }. This is all kind of fluffy, on both sides of our argument. Are we really concerned about cognitive load of for (;;) vs. for-in? That ship sailed long ago and I argue it's as likely that meta-programmable for-in heals the rift, as it is that iterate on top of enumerate makes a new rift. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
The most frequent (in my hearing) unsatisfied expectation of users of for-in is not that it is a second form after the C-based for(;;) -- there's no mention of for(;;). Rather, it is that for (v in [1,2,3]) fails to iterate 1,2,3, instead enumerating 0,1,2. We can't satisfy this Pythonic expectation directly, but with meta-programmable for-in, users and library authors can help themselves, using keys, values, and other iterator factory functions. Library authors can't really do this without providing their own array classes, modifying the array prototype would be too dangerous in a web environment to be done by a library as it would not work with other code that may expect current for-in behaviour, same applies to NodeList's, etc in the DOM. This is another reason i'm in favour of a different syntax - we could make it iterate values as people expect. Further complicating it feels like it would be a pedagogical nightmare. I think this is exaggerated -- there's really no relation to for(;;), and the first-year students move up and on. The nightmare of unprogrammable for-in, if I may use that word, is both the non-interoperable mess of for-in today in ES3-ES5-level browsers, plus the enumerate trap of tomorrow -- never mind an iterate trap. But most programmers do not need to know about proxies. I am most concerned about this making for-in much more complicated; Yes python has had meta-programmable objects forever (give or take a few years :D) which shows people can understand the behaviour, but the default behaviour exhibited in python is different, and more in line with what people expect. By changing for(in) behaviour in harmony you're trying to give python like meta-programming but with less than ideal defaults for new developers, and confusion for experienced developers. I think the other problem i have is that what people really seem to want is value enumeration of arrays (and array-likes), and by re-using the syntax you basically ensure that at the very least arrays (and other array-likes) will never get that behaviour by default. In addition to that it would be very dangerous for any library to override the iterate trap as libraries want to interact well with other libraries, and also provide a consistent development environment across multiple engines and versions. That leads me to expect that libraries would not override the enumerate trap. If we had a new syntax, in addition to allowing meta-programming from the get-go, we could also provide default enumerate traps for arrays, etc that is inline with what people expect. --Oliver ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
On Nov 22, 2010, at 7:07 PM, Oliver Hunt wrote: The most frequent (in my hearing) unsatisfied expectation of users of for-in is not that it is a second form after the C-based for(;;) -- there's no mention of for(;;). Rather, it is that for (v in [1,2,3]) fails to iterate 1,2,3, instead enumerating 0,1,2. We can't satisfy this Pythonic expectation directly, but with meta-programmable for-in, users and library authors can help themselves, using keys, values, and other iterator factory functions. Library authors can't really do this without providing their own array classes, modifying the array prototype would be too dangerous Modifying the array prototype isn't relevant here (proxies on the prototype do not iterate, they enumerate -- see prior mail with js shell session excerpts). Not sure what you mean if not this -- adding methods to Array.protoype? PrototypeJS does this. in a web environment to be done by a library as it would not work with other code that may expect current for-in behaviour, same applies to NodeList's, etc in the DOM. I think you're arguing against something not proposed. for (var v in values(a)) ... requires no prototype monkeypatching. Somehow inserting a proxy with a handler having an iterate trap at the front of the Array.prototype chain won't work as noted already. If you thought I meant this: for (var v in [1,2,3]) print(v); printing 1 2 3, as I wrote in words cited at the top of this message We can't satisfy this Pythonic expectation directly. Something like values would need to be called around the [1,2,3]. This is another reason i'm in favour of a different syntax - we could make it iterate values as people expect. I'm sure you are in favor of different syntax, but the argument you just made doesn't support that and it seems to have been based on a misunderstanding. Further complicating it feels like it would be a pedagogical nightmare. I think this is exaggerated -- there's really no relation to for(;;), and the first-year students move up and on. The nightmare of unprogrammable for-in, if I may use that word, is both the non-interoperable mess of for-in today in ES3-ES5-level browsers, plus the enumerate trap of tomorrow -- never mind an iterate trap. But most programmers do not need to know about proxies. I am most concerned about this making for-in much more complicated; Yes python has had meta-programmable objects forever (give or take a few years :D) which shows people can understand the behaviour, but the default behaviour exhibited in python is different, and more in line with what people expect. By changing for(in) behaviour in harmony you're trying to give python like meta-programming but with less than ideal defaults for new developers, and confusion for experienced developers. Let's not argue by asserting who will be confused. I've already replied to Allen that the sword has two edges, one pointed away from skilled programmers. It's simply selective arguing to say only bad things happen in one direction. You can get cut; you can cut someone not intended. The issue is not whether for-in should be meta-programmable -- Proxy has an enumerate trap -- but how much. I think the other problem i have is that what people really seem to want is value enumeration of arrays (and array-likes), and by re-using the syntax you basically ensure that at the very least arrays (and other array-likes) will never get that behaviour by default. If we wanted to change Harmony's runtime semantics to be even less compatible than it is with no global object, we could wave a spec-wand and do that. Why don't we? The reasons won't go away. The best we can do in any mostly-compatible spec edition is add new forms, whether syntax or API, and see if the cows beat new paths. Dave's early message then observed that if all the developer cows happily use the new iteration form, the old one is basically dead. Reforming for (var v in [1,2,3]) at that very late date to iterate over values, assuming such a compatibility break is acceptable, simply won't matter by the premise: the cows moved to the new field. In addition to that it would be very dangerous for any library to override the iterate trap as libraries want to interact well with other libraries, You can't override the iterate trap. Handlers are stratified and encapsulated. This is basic to the harmony:proxies design. and also provide a consistent development environment across multiple engines and versions. That leads me to expect that libraries would not override the enumerate trap. Do you mean wrap a proxy with a different proxy having a different enumerate or iterate trap? Wrapping is not overriding. No mutation, different object identities. I'm worried we are talking past each other now. If we had a new syntax, in addition to allowing meta-programming from the get-go, we could also provide default enumerate traps
Re: Nov 18 notes
On Nov 21, 2010, at 7:05 PM, Brendan Eich wrote: On Nov 18, 2010, at 4:08 PM, Waldemar Horwat wrote: Consensus that we should have iterators. For this, after all these years (JS1.7 added meta-programmable for-in in 2006), I'm grateful, although I wanted to add something your notes did not report: To get consensus, we made a tentative agreement to leave for-in as it was and not enable any meta-programmability of it, consigning it to the historically-underspecified and non-interoperable enumeration mystery-meat status. Instead, we did the committee-plays-it-safe thing of inventing new syntax for meta-programmable iteration: for (var i : x) ... This is a break from Python and JS1.7+ in SpiderMonkey and Rhino -- although it matches very late Java and C++ extensions that are similar (but not the same), and really not relevant to JS. Worse, the use of colon in this new for syntax is confusingly similar to long-standing future-proofing intentions around runtime type annotations (aka guards or contracts). (BTW, I don't think :: is a good type annotation or guard punctuator, btw -- it's the C++ namespace qualification operator, also specified for namespacing by ECMA-357 (E4X) and used that way in ActionScript 3 (and in ES4, RIP). So I was surprised to see :: used for annotation-like syntax in http://wiki.ecmascript.org/doku.php?id=strawman:guards and http://wiki.ecmascript.org/doku.php?id=strawman:trademarks.) for (var i : x) ... // must be new iteration for (var i : T : x) ... // iteration again, but parsed how? for (var i : T in x) ... // for-in with annotated var Depending on what T might be, grammatically, this could get sticky for top-down parsers. It is confusing and ugly in any event, IMHO. Probably we need to take our time and not rush into a meta-programming-here syntax variant of for-in. I'll not propose anything better right now. If the colon is less future-compatible than we like, why not: foreach (var i in x) While for is slightly more common for a loop that iterates a container, foreach is also quite common, and indeed is often used to name the construct even in languages where the keyword is spelled for: http://en.wikipedia.org/wiki/Foreach. This would allow us to reserve the colon, and also avoid a surprising change to the semantics of the existing for..in construct. It could even DTRT for arrays. Also, it will likely be easier for programmers to talk about the distinction between for..in loops and foreach..in loops than for..in loops and for..colon loops. Regards, Maciej ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
On Nov 22, 2010, at 11:19 PM, Maciej Stachowiak wrote: Probably we need to take our time and not rush into a meta-programming-here syntax variant of for-in. I'll not propose anything better right now. If the colon is less future-compatible than we like, why not: foreach (var i in x) All the new words are not reserved, so they could begin a function call expression in extant code: hi = there foreach (i in x) print(i) means hi = there; foreach(i in x); print(i); today. Same if you s/foreach/iterate/ or any non-reserved identifier. Wherefore Allen's co-opting of enum (plus with, a decent preposition given enum but 8 chars in two keywords hurt kittens everywhere). Anyway, the bikeshed is secondary. We need to agree on what meta-programmable for-in means with the enumerate trap (specified by the wiki pages on harmony:proxies), how that changes with the optional iterate trap (strawman:iterators), and when it might matter (for all for-in loops, or only those in Harmony code?). /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
On Nov 18, 2010, at 4:08 PM, Waldemar Horwat wrote: Consensus that we should have iterators. For this, after all these years (JS1.7 added meta-programmable for-in in 2006), I'm grateful, although I wanted to add something your notes did not report: To get consensus, we made a tentative agreement to leave for-in as it was and not enable any meta-programmability of it, consigning it to the historically-underspecified and non-interoperable enumeration mystery-meat status. Instead, we did the committee-plays-it-safe thing of inventing new syntax for meta-programmable iteration: for (var i : x) ... This is a break from Python and JS1.7+ in SpiderMonkey and Rhino -- although it matches very late Java and C++ extensions that are similar (but not the same), and really not relevant to JS. Worse, the use of colon in this new for syntax is confusingly similar to long-standing future-proofing intentions around runtime type annotations (aka guards or contracts). (BTW, I don't think :: is a good type annotation or guard punctuator, btw -- it's the C++ namespace qualification operator, also specified for namespacing by ECMA-357 (E4X) and used that way in ActionScript 3 (and in ES4, RIP). So I was surprised to see :: used for annotation-like syntax in http://wiki.ecmascript.org/doku.php?id=strawman:guards and http://wiki.ecmascript.org/doku.php?id=strawman:trademarks.) for (var i : x) ... // must be new iteration for (var i : T : x) ... // iteration again, but parsed how? for (var i : T in x) ... // for-in with annotated var Depending on what T might be, grammatically, this could get sticky for top-down parsers. It is confusing and ugly in any event, IMHO. Probably we need to take our time and not rush into a meta-programming-here syntax variant of for-in. I'll not propose anything better right now. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
On Nov 21, 2010, at 7:21 PM, Chris Sells wrote: I'm a huge fan of iterators. As far as index goes, I'm not a fan of the use of the colon. We should take our time, but something that I wanted to throw into the pot would be to build on the key-based nature of for-in with syntax like this: forvals ( var x in xs ) {...} Also, have we given any thought to making it easier to implement custom iterators ala the C# yield return operator? We've prototyped and shipped generators based on Python 2.5 (with a simplification that avoids introducing GeneratorExit) for years, in SpiderMonkey and Rhino. The yield operator is a low-precedence expression prefix whose presence in a function makes it a generator. Wiki link: http://wiki.ecmascript.org/doku.php?id=strawman:generatorss=generators This strawman wil be revised based on specific feedback (put something in the function preamble, not just yield expressions in the body, to make it clearly a generator, and the yield-in-try-with-finally argument), and prepared for discussion at the January 2011 TC39 meeting. /be -Original Message- From: es-discuss-boun...@mozilla.org [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Brendan Eich Sent: Sunday, November 21, 2010 7:05 PM To: Waldemar Horwat Cc: Mark S. Miller; es-discuss Subject: Re: Nov 18 notes On Nov 18, 2010, at 4:08 PM, Waldemar Horwat wrote: Consensus that we should have iterators. For this, after all these years (JS1.7 added meta-programmable for-in in 2006), I'm grateful, although I wanted to add something your notes did not report: To get consensus, we made a tentative agreement to leave for-in as it was and not enable any meta-programmability of it, consigning it to the historically-underspecified and non-interoperable enumeration mystery-meat status. Instead, we did the committee-plays-it-safe thing of inventing new syntax for meta-programmable iteration: for (var i : x) ... This is a break from Python and JS1.7+ in SpiderMonkey and Rhino -- although it matches very late Java and C++ extensions that are similar (but not the same), and really not relevant to JS. Worse, the use of colon in this new for syntax is confusingly similar to long-standing future-proofing intentions around runtime type annotations (aka guards or contracts). (BTW, I don't think :: is a good type annotation or guard punctuator, btw -- it's the C++ namespace qualification operator, also specified for namespacing by ECMA-357 (E4X) and used that way in ActionScript 3 (and in ES4, RIP). So I was surprised to see :: used for annotation-like syntax in http://wiki.ecmascript.org/doku.php?id=strawman:guards and http://wiki.ecmascript.org/doku.php?id=strawman:trademarks.) for (var i : x) ... // must be new iteration for (var i : T : x) ... // iteration again, but parsed how? for (var i : T in x) ... // for-in with annotated var Depending on what T might be, grammatically, this could get sticky for top-down parsers. It is confusing and ugly in any event, IMHO. Probably we need to take our time and not rush into a meta-programming-here syntax variant of for-in. I'll not propose anything better right now. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
On Nov 21, 2010, at 7:21 PM, Chris Sells wrote: I'm a huge fan of iterators. As far as index goes, I'm not a fan of the use of the colon. We should take our time, but something that I wanted to throw into the pot would be to build on the key-based nature of for-in with syntax like this: forvals ( var x in xs ) {...} Resist bikeshedding early and all that, but there's already a strike against this or anything like it: JS lacks run-together keywords apart from typeof and instanceof, which do not abbreviate as vals does. In grasping for : instead of in, the committee was trying to keep the introductory keyword for. I think we had agreement that sticking with for is still worth using as a syntax design guide or back up and try another route forward [than 'in'] design point. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
On Nov 21, 2010, at 7:41 PM, Brendan Eich wrote: On Nov 21, 2010, at 7:21 PM, Chris Sells wrote: I'm a huge fan of iterators. As far as index goes, I'm not a fan of the use of the colon. We should take our time, but something that I wanted to throw into the pot would be to build on the key-based nature of for-in with syntax like this: forvals ( var x in xs ) {...} Resist bikeshedding early and all that, but there's already a strike against this or anything like it: JS lacks run-together keywords apart from typeof and instanceof, which do not abbreviate as vals does. In grasping for : instead of in, the committee was trying to keep the introductory keyword for. I think we had agreement that sticking with for is still worth using as a syntax design guide or back up and try another route forward [than 'in'] design point. And (sorry, I'll try to keep replies in one message next time) for vs. forvals does not exactly scream keys vs. values, since for is only about keys if you know ECMA-262 and expect the mystery meat of enumeration. If we manage to make normative specifications for enumeration, which has been a goal recently, we'll still have for-in for that keys meaning. So there won' t be any keys : vals symmetry to play off of, just some longer or different syntax for meta-programmable iteration. Which raises another point: meta-programmable iteration is not necessarily about values and not keys. A custom iterator could (and in the strawman does) return key/value pairs. The whole keys vs. values dilemma is a false one here. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nov 18 notes
And (sorry, I'll try to keep replies in one message next time) for vs. forvals does not exactly scream keys vs. values, since for is only about keys if you know ECMA-262 and expect the mystery meat of enumeration. IMO, forvals is a non-starter, as is foreach or for each. The for part of the syntax denotes quantification, and the stuff to the right of the variable denotes what is being iterated. In all cases, we are talking about universal quantification, so they should all be for. Which raises another point: meta-programmable iteration is not necessarily about values and not keys. A custom iterator could (and in the strawman does) return key/value pairs. The whole keys vs. values dilemma is a false one here. Indeed. There are an unbounded number of types of sequences that can be iterated over. Whether we provide 2 or 200 it will never be enough. Hence the need for a general, programmable iteration mechanism. Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss