Re: destructuring: as patterns?
On 21 April 2012 11:56, Herby Vojčík he...@mailbox.sk wrote: Andreas Rossberg wrote: Of course, it is absolutely true that the same argument can be made about someExpression.x, but I file that under historic legacy. If we were to design JS from scratch -- and with the ES6 feature set! -- then I'd surely vote for making that throw as well (like, btw, I would for argument arity mismatches in function calls, if the callee doesn't have appropriate default or rest parameters). Clearly, it's not possible to correct that, but why should that imply that all new features need to inherit sloppy semantics, too? I disagree. Borrowing from Alan Kay IIRC, this is like making an octopus from a dog by nailing more legs on it - that is, these two points of view are incompatible. Well, that already is the case. ES5 added strict mode. With 1JS in ES6, the rules may get more fuzzy. You gonna have 'let' vs 'var'. You gonna have '=' vs 'function'. You gonna have 'for-of' vs 'for-in'. All additions that fit your description. It's not pretty, but bolting on new legs next to the old ones is the only way to keep a language like JS moving forward. JS model _is_ about sloppy semantics (I do not call it sloopy, I'd rather called it liberal), that is, undefined if not present. It's a term sometimes used on TC39, I didn't invent it (I used to call it classic mode for improved neutrality). I may take issues with associating pre-strict-mode sweeping under the rug with liberal ideals, though. :) /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
On Apr 23, 2012, at 2:40 AM, Andreas Rossberg wrote: On 21 April 2012 11:56, Herby Vojčík he...@mailbox.sk wrote: ... JS model _is_ about sloppy semantics (I do not call it sloopy, I'd rather called it liberal), that is, undefined if not present. It's a term sometimes used on TC39, I didn't invent it (I used to call it classic mode for improved neutrality). I may take issues with associating pre-strict-mode sweeping under the rug with liberal ideals, though. :) I like Martin Rinard's concept of code that is failure oblivious http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.68.9926rep=rep1type=pdf Arguably, the robustness of the web is dependent up the fact many Javascript based webpages will continue to operate, perhaps in a slight degraded mode, even in the face of runtime errors. I'm all for early errors that cause a structurally ill-formed script from loading. But for a well-formed program I don't see why throwing a (probably uncaught) exception is necessarily any more robust than simply returning undefined when various dynamic failures (such as the destructuring situations we are talking about) are encountered. To me, undefined propagation feels a lot like NaN propagation in numeric expressions. Those of us who don't do a lot of numeric computation may be puzzled by NaNs, but it is a lot easier to simply let a NaN propagate through a complex formula and check it at the end, then it is to check for an exception on each operation of the formula. And, sometimes it turns out that the NaN didn't really matter at all... It is important that JavaScript programmer are able to harden the failure critical portions of their applications. Trying to automatically harden everything may actually make JS a less useful languages. Allen___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
On 21 April 2012 01:08, Brendan Eich bren...@mozilla.org wrote: Allen Wirfs-Brock wrote: What I'm really pushing at here is the throw. Let's are used for establishing and initializing bindings. From a binding perspective: let x ; and let {x} = {}; are almost exactly the same thing. They both establish a hoisted uninitialized lexical binding for x. They both delimit the end of the TDZ for x. They both supply undefined as the initialization value of x. Why should the second form throw when the first doesn't? That is a good question. It's about expression of intent. When you write let x; it is syntactic sugar for let x = undefined; So clearly, you want x to be undefined, and you pretty much said so explicitly. However, nobody ever writes let {x} = {}; What destructuring is meant for, and what programmers write in reality is let {x, y} = someExpressionThatIsNotALiteral and here, the apparent intention is that someExpression results in an object with an x and y property. If it doesn't, that typically means there is a bug. And masking a bug and/or letting it proliferate silently is rarely a good idea. Much less so if the language does it implicitly. Now, a stricter semantics does not preclude that the language provides some convenient way to also express the sloppy intent for the cases where you really want it, which is what Brendan's ?-operator would do. So I'd be happy with that, as long as it is sufficiently explicit and not the default. Of course, it is absolutely true that the same argument can be made about someExpression.x, but I file that under historic legacy. If we were to design JS from scratch -- and with the ES6 feature set! -- then I'd surely vote for making that throw as well (like, btw, I would for argument arity mismatches in function calls, if the callee doesn't have appropriate default or rest parameters). Clearly, it's not possible to correct that, but why should that imply that all new features need to inherit sloppy semantics, too? /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
Andreas Rossberg wrote: On 21 April 2012 01:08, Brendan Eichbren...@mozilla.org wrote: Allen Wirfs-Brock wrote: What I'm really pushing at here is the throw. Let's are used for establishing and initializing bindings. From a binding perspective: let x ; and let {x} = {}; are almost exactly the same thing. They both establish a hoisted uninitialized lexical binding for x. They both delimit the end of the TDZ for x. They both supply undefined as the initialization value of x. Why should the second form throw when the first doesn't? That is a good question. It's about expression of intent. When you write let x; it is syntactic sugar for let x = undefined; So clearly, you want x to be undefined, and you pretty much said so explicitly. However, nobody ever writes let {x} = {}; What destructuring is meant for, and what programmers write in reality is let {x, y} = someExpressionThatIsNotALiteral and here, the apparent intention is that someExpression results in an object with an x and y property. If it doesn't, that typically means there is a bug. And masking a bug and/or letting it proliferate silently is rarely a good idea. Much less so if the language does it implicitly. Now, a stricter semantics does not preclude that the language provides some convenient way to also express the sloppy intent for the cases where you really want it, which is what Brendan's ?-operator would do. So I'd be happy with that, as long as it is sufficiently explicit and not the default. Of course, it is absolutely true that the same argument can be made about someExpression.x, but I file that under historic legacy. If we were to design JS from scratch -- and with the ES6 feature set! -- then I'd surely vote for making that throw as well (like, btw, I would for argument arity mismatches in function calls, if the callee doesn't have appropriate default or rest parameters). Clearly, it's not possible to correct that, but why should that imply that all new features need to inherit sloppy semantics, too? I disagree. Borrowing from Alan Kay IIRC, this is like making an octopus from a dog by nailing more legs on it - that is, these two points of view are incompatible. JS model _is_ about sloppy semantics (I do not call it sloopy, I'd rather called it liberal), that is, undefined if not present. It should not be changed in other part of languages as well, or it will be mess of learning where this applies and where opposite of this applies. /Andreas Herby ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
Andreas Rossberg wrote: Clearly, it's not possible to correct that, but why should that imply that all new features need to inherit sloppy semantics, too? There's no strict logical implication. On the plus side, the new features are stricter (if you are pro-strict and anti-sloppy -- let's assume we all agree on this, pace Herby). On the minus side, you're making the language a mixture of strictness that is more complicated (who cares about legacy?) and possibly harder to use in practice. The in practice part is crucial. We've all had bugs in JS code where you pull out undefined (due to a property name typo, e.g. -- more insidiously due to type confusion) and it flows way downstream before someone notices. This is a pain. But it's in the language. Does trying to close the barn door only for destructuring -- closing the new upper half of the dutch-style door -- help? The lower half is wide open. Users who want the strictness can use destructuring always: let {p} = o; instead of let p = o.p; and get an error on missing o.p -- that could be the new style for those wanting to avoid the legacy behavior. If that's the idea, I get it. But I'm skeptical that such an intentional style will be adopted widely, or at all. There's no help for all the open-coded if (o.p) ... foo(o.p) etc. uses that evaluate to undefined when p is not in o. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
On 20 April 2012 02:15, Allen Wirfs-Brock al...@wirfs-brock.com wrote: On Apr 19, 2012, at 4:16 PM, David Herman wrote: let { unidentifiedAdult: mom as dad, unidentifiedChild: sister as brother } or let { undentifiedAdult as mom as dad, unidentifiedChild as sister as brother } I actually I found propertyName : bindingIdentifier as bindingPattern (do I have the subparts right?) somewhat confusing at first and I think other might also. What is the difference between : and |as|? Essentially the same as the difference between : and = in expressions. Having said that, I don't like Dave's suggestion of overloading 'as' for object destructuring. I agree that object patterns may be confusing at first, but you also get used to that quickly. And overloading 'as' is probably even more confusing, as this discussion already shows. Why are different things allowed after each? Only one |as|? I actually think your second alternative is clearer but why not: let {unidentifiedAdult : mom : dad : auntie, unidentifiedChild : sister : brother} = peopleComstants. *gulp* Not sure if that was a serious suggestion, but let me emphasize again that layered patterns need to be _compositional_, because you want to be able to use them in other places, e.g. parameter lists. Tying them to one particular, unrelated destructuring construct is not right. If you think about destructuring simply as an alternative initialization syntax that seems to make more sense. Essentially : and = are duals that operate in opposite directions: let {unidentifiedAdult : mom : dad : auntie} = peopleComstants; //right to left initialization vs let mom = dad = auntie = peopleComstants. unidentifiedAdult; //left to right initialization I disagree. That is a bogus analogy. An object pattern is completely different from a 'let'. In particular, the latter binds 'mom', but not 'dad' and 'auntie'. The proper equivalence (I wouldn't call it a duality) would be let {unidentifiedAdult : mom as dad as auntie} = peopleComstants; vs let mom as dad as auntie = peopleComstants.unidentifiedAdult; You cannot even express it without a compositional 'as'. /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
Andreas Rossberg wrote: I disagree. That is a bogus analogy. An object pattern is completely different from a 'let'. In particular, the latter binds 'mom', but not 'dad' and 'auntie'. The proper equivalence (I wouldn't call it a duality) Right. The duality I've cited is between let o = {p: q}; and let {p: q} = o; where q and o change places. Dave's suggestion of let {p as q} = o; does read better in my subjective opinion, even though it diverges the pattern langauge (moreso; already diverged) from the object literal language. would be let {unidentifiedAdult : mom as dad as auntie} = peopleComstants; vs let mom as dad as auntie = peopleComstants.unidentifiedAdult; You cannot even express it without a compositional 'as'. Agreed. But is it unthinkable to have 'as' (compositional of course) in the pattern language only? I bow to your SuccessorML skills :-). /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
On Apr 20, 2012, at 2:16 AM, Andreas Rossberg wrote: On 20 April 2012 02:15, Allen Wirfs-Brock al...@wirfs-brock.com wrote: On Apr 19, 2012, at 4:16 PM, David Herman wrote: let { unidentifiedAdult: mom as dad, unidentifiedChild: sister as brother } or let { undentifiedAdult as mom as dad, unidentifiedChild as sister as brother } I actually I found propertyName : bindingIdentifier as bindingPattern (do I have the subparts right?) somewhat confusing at first and I think other might also. What is the difference between : and |as|? Essentially the same as the difference between : and = in expressions. I don't understand. : isn't used in expressions and the productions to the right of an = doesn't introduce any bindings. The : as syntax seems to contain identifier bindings in both what follows : and what follows as. How is : and as different other than which binding forms are allowed after each? Having said that, I don't like Dave's suggestion of overloading 'as' for object destructuring. I agree that object patterns may be confusing at first, but you also get used to that quickly. And overloading 'as' is probably even more confusing, as this discussion already shows. Why are different things allowed after each? Only one |as|? I actually think your second alternative is clearer but why not: let {unidentifiedAdult : mom : dad : auntie, unidentifiedChild : sister : brother} = peopleComstants. *gulp* Not sure if that was a serious suggestion, but let me emphasize again that layered patterns need to be _compositional_, because you want to be able to use them in other places, e.g. parameter lists. Tying them to one particular, unrelated destructuring construct is not right. What's not compositional about the above? I'm not going to quote the whole BNF from the draft specification but the key productions are: BindingPattern : ObjectBindingPattern ArrayBindingPattern ObjectBindingPattern : { BindingPropertyList } ArrayBindingPattern : [ BindingElementList ] BindingProperty : PropertyName : BindingElement BindingElement : BindingIdentifier BindingPattern All I was saying is that references to BindingElement in that grammar could be replaced with Bindings defined as Bindings : Bindings : BindingElement BindingElement Still completely compositional. It is simply permitting a single value from the source object to be used as the initializer of multiple bindings. This could work anywhere, include argument lists. If you think about destructuring simply as an alternative initialization syntax that seems to make more sense. Essentially : and = are duals that operate in opposite directions: let {unidentifiedAdult : mom : dad : auntie} = peopleComstants; //right to left initialization vs let mom = dad = auntie = peopleComstants. unidentifiedAdult; //left to right initialization I disagree. That is a bogus analogy. An object pattern is completely different from a 'let'. In particular, the latter binds 'mom', but not 'dad' and 'auntie'. You're right, I made the mistake of thinking that the assignments in the let initializer were binding forms. They aren't. I'm sure others will make this same mistake. It makes me want to restrict assignment operators in let/const initializers! The proper equivalence (I wouldn't call it a duality) would be let {unidentifiedAdult : mom as dad as auntie} = peopleComstants; vs let mom as dad as auntie = peopleComstants.unidentifiedAdult; or, since we are making up syntax: let mom : dad : auntie = peopleComstants.unidentifiedAdult; or let (mom, dad, auntie) = peopleComstants.unidentifiedAdult; You cannot even express it without a compositional 'as'. or something... /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
Andreas Rossberg wrote: On 20 April 2012 17:12, Brendan Eichbren...@mozilla.org wrote: But is it unthinkable to have 'as' (compositional of course) in the pattern language only? Perhaps, but what exactly do you mean? ;) Patterns can have custom grammar in binding contexts (after let, in catch heads, etc.), whereas in an assignment expression's left-hand side we'd need ObjectLiteral and ArrayLiteral to cover the grammar. I sense trouble trying to add 'as' to the expression grammar (AssignmentExpression to be precise). We could parse it and reject it with supplemental syntax for rvalues, and allow it in lvalues, but there is a spec smell. I think from past discussions that TC39 wants the grammar to be as precise as possible while still LR(1) with lookahead and other restrictions. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
On 20 April 2012 17:53, Allen Wirfs-Brock al...@wirfs-brock.com wrote: On Apr 20, 2012, at 2:16 AM, Andreas Rossberg wrote: On 20 April 2012 02:15, Allen Wirfs-Brock al...@wirfs-brock.com wrote: On Apr 19, 2012, at 4:16 PM, David Herman wrote: let { unidentifiedAdult: mom as dad, unidentifiedChild: sister as brother } or let { undentifiedAdult as mom as dad, unidentifiedChild as sister as brother } I actually I found propertyName : bindingIdentifier as bindingPattern (do I have the subparts right?) somewhat confusing at first and I think other might also. What is the difference between : and |as|? Essentially the same as the difference between : and = in expressions. I don't understand. : isn't used in expressions and the productions to the right of an = doesn't introduce any bindings. The : as syntax seems to contain identifier bindings in both what follows : and what follows as. How is : and as different other than which binding forms are allowed after each? Maybe we are talking past each other, but why do you say : isn't used in expressions? It's part of the syntax of object literals, and I think it should keep the same meaning in patterns. On the other hand, you have an expression form 'e1 = e2', where all free variables are use-sites. Analogously, in patterns you have 'p1 as p2' (at least if you think of the most general form), where all free variables are binding sites (because that's the very nature of a pattern). What's left of : in an object literal is not a variable, in neither expressions nor patterns. That's why I think you shouldn't conflate : and 'as', neither one way (Dave's suggestion) nor the other (your suggestion). What's not compositional about the above? I'm not going to quote the whole BNF from the draft specification but the key productions are: BindingPattern : ObjectBindingPattern ArrayBindingPattern ObjectBindingPattern : { BindingPropertyList } ArrayBindingPattern : [ BindingElementList ] BindingProperty : PropertyName : BindingElement BindingElement : BindingIdentifier BindingPattern All I was saying is that references to BindingElement in that grammar could be replaced with Bindings defined as Bindings : Bindings : BindingElement BindingElement Still completely compositional. It is simply permitting a single value from the source object to be used as the initializer of multiple bindings. This could work anywhere, include argument lists. OK, I thought you wanted to tie it to BindingPropertyList. Still, BindingElement seems to be the wrong place. According to the current grammar, it would not allow me to write any of let x as {a, b} = bla for (let x as {a, b} of bla) ... {set c(x as {a, b}) {...}} try { ...} catch (x as {a, b}) { ... } That is, the canonical place in the grammar would be BindingPattern AFAICS. or, since we are making up syntax: let mom : dad : auntie = peopleComstants.unidentifiedAdult; or let (mom, dad, auntie) = peopleComstants.unidentifiedAdult; The latter looks far too much like a tuple, and would be particularly confusing in a parameter list, I'd say. /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
On 20 April 2012 18:18, Brendan Eich bren...@mozilla.org wrote: Patterns can have custom grammar in binding contexts (after let, in catch heads, etc.), whereas in an assignment expression's left-hand side we'd need ObjectLiteral and ArrayLiteral to cover the grammar. I sense trouble trying to add 'as' to the expression grammar (AssignmentExpression to be precise). We could parse it and reject it with supplemental syntax for rvalues, and allow it in lvalues, but there is a spec smell. I think from past discussions that TC39 wants the grammar to be as precise as possible while still LR(1) with lookahead and other restrictions. I see, I haven't thought of destructuring assignment. Yes, that's a bit of an annoyance. But IMHO not a big issue either. Honestly, my feeling is that strictly sticking to that principle will overly constrain pattern syntax anyway, if not for 'as' then for the next nice feature. I dimly remember that we had it coming up before. One alternative of course would be to restrict what can occur in an assignment pattern, compared to bindings. The two are quite different semantically, so it could perhaps be argued. But it's not the most pleasant idea either. /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
Andreas Rossberg wrote: Honestly, my feeling is that strictly sticking to that principle will overly constrain pattern syntax anyway, if not for 'as' then for the next nice feature. I dimly remember that we had it coming up before. Dave and I were talking about making fail-soft or irrefutable match opt-in: js let {x} = {}; js x (SpiderMonkey shell.) IOW, destructuring has been conceived of as pretty thin sugar for getting a property, and if no such property, you get undefined. Of course, this makes a deeper pattern fail hard: js let {y:{z}} = {}; typein:4: TypeError: (void 0) is undefined (Atrocious SpiderMonkey failure to pretty-print the blamed expression instead of its portable (void 0) value there -- my fault I think.) Dave suggested making the first case, let {x} = {}, throw, and requiring ? as a pattern modifier (I suggested prefix): let {?x} = {}; // x is undefined, no throw let {y} = {}; // throws So there's another place the pattern language wants to diverge from object literal notation. One alternative of course would be to restrict what can occur in an assignment pattern, compared to bindings. The two are quite different semantically, so it could perhaps be argued. But it's not the most pleasant idea either. Turns out Allen has already done this in ES6 drafts. 11.13.1 is for destructuring assignment. 12.2.4 is destructuring binding patterns. So we can diverge patterns further. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
Brendan Eich wrote: Dave suggested making the first case, let {x} = {}, throw, and requiring ? as a pattern modifier (I suggested prefix): let {?x} = {}; // x is undefined, no throw let {y} = {}; // throw I forgot to mention something Dave noticed. Should let {?x:{y}} = {}; This too would not throw, rather it would bind y to undefined -- unlike the get-undefined-and-then-fail-trying-to-get-y-from-it approach of destructuring as implemented in SpiderMonkey and Rhino (based on ES4, then ES6 drafts). So ? as pattern prefix is a deep opt-in flag. Thoughts? /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
Brendan Eich wrote: Should let {?x:{y}} = {}; I lost a line finishing the obvious Should ... throw? question. We could make ? shallow and require another ?-prefix to avoid the throw: let {?x:{?y}} = {} but that seems like it might be user-hostile. CoffeeScript has ?. and ?( fail-soft operators which are quite popular. We talked about them last over a year ago, IIRC. Not proposing them here but citing them as nearby, and noting that CoffeeScript does require a ?. per level: coffee a = {} {} coffee a.?b Error: In repl, Parse error on line 1: Unexpected '?' ... coffee a?.b undefined coffee a?.b.c TypeError: Cannot read property 'c' of undefined ... coffee a?.b?.c undefined /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
On Apr 20, 2012, at 2:22 PM, Brendan Eich wrote: Andreas Rossberg wrote: Honestly, my feeling is that strictly sticking to that principle will overly constrain pattern syntax anyway, if not for 'as' then for the next nice feature. I dimly remember that we had it coming up before. Dave and I were talking about making fail-soft or irrefutable match opt-in: js let {x} = {}; js x (SpiderMonkey shell.) IOW, destructuring has been conceived of as pretty thin sugar for getting a property, and if no such property, you get undefined. Of course, this makes a deeper pattern fail hard: But also remember that we allow default value expressions in binding patterns (but not destructuring assignments, where they would be ambiguous): let (x=default} = {}; print(x); //default js let {y:{z}} = {}; typein:4: TypeError: (void 0) is undefined alternatively: let {y:{z} = {z:default}} = {}; or let {y:{z = default}} = {}; (Atrocious SpiderMonkey failure to pretty-print the blamed expression instead of its portable (void 0) value there -- my fault I think.) Dave suggested making the first case, let {x} = {}, throw, and requiring ? as a pattern modifier (I suggested prefix): Then shouldn't let x; be illegal? Would you have to say: let ?x; let {?x} = {}; // x is undefined, no throw let {y} = {}; // throws so, why not: let {x=undefined} = {}; So there's another place the pattern language wants to diverge from object literal notation. One alternative of course would be to restrict what can occur in an assignment pattern, compared to bindings. The two are quite different semantically, so it could perhaps be argued. But it's not the most pleasant idea either. Turns out Allen has already done this in ES6 drafts. 11.13.1 is for destructuring assignment. 12.2.4 is destructuring binding patterns. So we can diverge patterns further. /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: destructuring: as patterns?
Allen Wirfs-Brock wrote: js let {y:{z}} = {}; typein:4: TypeError: (void 0) is undefined alternatively: let {y:{z} = {z:default}} = {}; or let {y:{z = default}} = {}; Too verbose, for one. (Atrocious SpiderMonkey failure to pretty-print the blamed expression instead of its portable (void 0) value there -- my fault I think.) Dave suggested making the first case, let {x} = {}, throw, and requiring ? as a pattern modifier (I suggested prefix): Then shouldn't let x; be illegal? No. I know destructuring requires an initialiser but let does not and I think should not. It's a different beast. What you seem to be suggesting is that we relax the initialiser requirement, not that we ban let x. Would you have to say: let ?x; No way! let {?x} = {}; // x is undefined, no throw let {y} = {}; // throws so, why not: let {x=undefined} = {}; Again, too verbose and (this is the part I left out, see followup) not deep. How would defaulting work here? let {x:{y:{z}}} = {}; /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
On Apr 20, 2012, at 2:43 PM, Brendan Eich wrote: Allen Wirfs-Brock wrote: js let {y:{z}} = {}; typein:4: TypeError: (void 0) is undefined alternatively: let {y:{z} = {z:default}} = {}; or let {y:{z = default}} = {}; Too verbose, for one. (Atrocious SpiderMonkey failure to pretty-print the blamed expression instead of its portable (void 0) value there -- my fault I think.) Dave suggested making the first case, let {x} = {}, throw, and requiring ? as a pattern modifier (I suggested prefix): Then shouldn't let x; be illegal? No. I know destructuring requires an initialiser but let does not and I think should not. It's a different beast. What you seem to be suggesting is that we relax the initialiser requirement, not that we ban let x. Would you have to say: let ?x; No way! What I'm really pushing at here is the throw. Let's are used for establishing and initializing bindings. From a binding perspective: let x ; and let {x} = {}; are almost exactly the same thing. They both establish a hoisted uninitialized lexical binding for x. They both delimit the end of the TDZ for x. They both supply undefined as the initialization value of x. Why should the second form throw when the first doesn't Or, here is another way to think about it: let tmp1 = {}; let x = temp1.x; I don't think anybody is suggesting that the above should throw on the let initialization of x. so why should let {x} = {}; which is just a refactoring of the same bindings and accesses. let {?x} = {}; // x is undefined, no throw let {y} = {}; // throws so, why not: let {x=undefined} = {}; Again, too verbose which is why we allow the =undefined to be left out and it don't throw. What I think is going on in this discussion is a difference between viewing destructuuring as a shorthand (relative to the desugaring I used above) for initializing bindings and thinking of desugaring as a pattern matching operation. Desugaring isn't generalized pattern matching (see, http://blog.fogus.me/2011/01/14/pattern-matching-vs-destructuring-electric-boogaloo/ and http://www.mail-archive.com/es-discuss@mozilla.org/msg11341.html ). This is quite clear when you look at what is going on from the perspective of its specification. and (this is the part I left out, see followup) not deep. How would defaulting work here? let {x:{y:{z}}} = {}; let {x:{y:{z}} = {y:{z:defaultZ}}} = {}; //note that z is the only bound name above /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
Allen Wirfs-Brock wrote: What I'm really pushing at here is the throw. Let's are used for establishing and initializing bindings. From a binding perspective: let x ; and let {x} = {}; are almost exactly the same thing. They both establish a hoisted uninitialized lexical binding for x. They both delimit the end of the TDZ for x. They both supply undefined as the initialization value of x. Why should the second form throw when the first doesn't? That is a good question. Lars Hansen spec'ed destructuring for ES4 based on the array-pattern destructuring he had implemented in Opera, which does not throw. It plucks out undefined, of course, and trying to destructure deeper from undefined will throw. This is what we implemented in JS1.7+ in SpiderMonkey and Rhino. Andreas and Dave can make the throwing case better than I, so I will tag one or both of them in. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
On 19 April 2012 00:45, Allen Wirfs-Brock al...@wirfs-brock.com wrote: On Apr 18, 2012, at 2:48 PM, Brendan Eich wrote: David Herman wrote: *Please*, let's do this right. This says to me (what I originally expected) that duplicate property name at any ply in an object pattern should be an early error. Anyone disagree? I wholeheartedly agree. I'm not sure that the concern about repeated side-effects is very significant given that any property access can have arbitrary side-effects including adding and removing properties from the RHS object. I agree with that, too, though my impression is that implementations already get the exact sequences of such observable steps wrong in quite a few other cases (I played around with corner cases when doing proxies). The case above looks easy enough, but in general, the fewer possible micro observations the better. /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
On Apr 18, 2012, at 2:48 PM, Brendan Eich wrote: David Herman wrote: *Please*, let's do this right. This says to me (what I originally expected) that duplicate property name at any ply in an object pattern should be an early error. Anyone disagree? I got as far as being ready to type into the spec. the first line to implement this restriction. Then my reservations flamed-up. If you think of a destructuring declaration as simply a way to provide the initial values to a set of declaration is isn't so clear that duplicate property names are bogus. Consider: //initialize some variable with default objects let { unidentifedAdult: mom, unidetifiedAdult: dad, unidentiedChild: brother, unidentifiedChild: sister } = peopleConstants; why is this less desirable than: //initialize some variable with default objects let mon = peopleConstants.unidentifiedAdult, dad = peopleConstants.unidentifiedAdult, brother = peopleConstants.unidentifiedChild, sister = peopleConstants.unidentifiedChild; The former style is less familiar, but is it really bad enough to disallow at the language level? Disallowing duplicate property names may make sense if you think about destructuring in ES declarations as pattern matching (which it really isn't) or a means to break a composite into its constituent parts. But duplicate properties as initializers for a set of variables seem quite reasonable. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
On Apr 19, 2012, at 2:18 PM, Allen Wirfs-Brock wrote: //initialize some variable with default objects let { unidentifedAdult: mom, unidetifiedAdult: dad, unidentiedChild: brother, unidentifiedChild: sister } = peopleConstants; why is this less desirable than: //initialize some variable with default objects let mon = peopleConstants.unidentifiedAdult, dad = peopleConstants.unidentifiedAdult, brother = peopleConstants.unidentifiedChild, sister = peopleConstants.unidentifiedChild; Well, it's rare that you *need* to re-evaluate the dot-pattern. It saves typing, repetition (DRY!), side-effects, and running time to evaluate each selector only once: let mom = peopleConstants.unidentifiedAdult, dad = mom, brother = peopleConstants.unidentifiedChild, sister = brother; And you should be able to do that just fine with nested as-patterns: let { unidentifiedAdult: mom as dad, unidentifiedChild: sister as brother } or let { undentifiedAdult as mom as dad, unidentifiedChild as sister as brother } Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
destructuring: as patterns?
Looking through the destructuring proposal http://wiki.ecmascript.org/doku.php?id=harmony:destructuring there seems to be no mention of 'as' patterns. In typical pattern matching constructs (SML, Haskell, ..), 'as' patterns allow to name a sub-object while continuing the match for its sub-structures. For instance, with var obj = { a: 0, b: { x: 1, y: 2} }; something like let { b: b as {x,y} } = obj would result in the bindings of b to obj.b, x to obj.b.x, y to obj.b.y. This avoids needless repetition when both a subobject and its components need to be extracted. Without 'as', each such case leads to a separate destructuring assignment let { b } = obj let { b: {x,y} } = obj Shouldn't 'as' patterns be included in destructuring? Or have I missed an equivalent feature? Claus ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
We've supported destructuring for years and no one has asked for this. I say YAGNI and when in doubt, leave it out. One can always write two destructuring declarations without much repetition: let {b} = obj; let {x,y} = b; but of course one would just write let {x, y} = obj.b; in that contrived case. Main thing is, not having as-patterns is not a big deal based on experience with JS1.7+ since 2006 in Mozilla code. /be Claus Reinke wrote: Looking through the destructuring proposal http://wiki.ecmascript.org/doku.php?id=harmony:destructuring there seems to be no mention of 'as' patterns. In typical pattern matching constructs (SML, Haskell, ..), 'as' patterns allow to name a sub-object while continuing the match for its sub-structures. For instance, with var obj = { a: 0, b: { x: 1, y: 2} }; something like let { b: b as {x,y} } = obj would result in the bindings of b to obj.b, x to obj.b.x, y to obj.b.y. This avoids needless repetition when both a subobject and its components need to be extracted. Without 'as', each such case leads to a separate destructuring assignment let { b } = obj let { b: {x,y} } = obj Shouldn't 'as' patterns be included in destructuring? Or have I missed an equivalent feature? Claus ___ 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: destructuring: as patterns?
On Wed, Apr 18, 2012 at 11:26 AM, Brendan Eich bren...@mozilla.org wrote: We've supported destructuring for years and no one has asked for this. I say YAGNI and when in doubt, leave it out. One can always write two destructuring declarations without much repetition: But who has been using it? Certainly not the general JS development community. let {b} = obj; let {x,y} = b; but of course one would just write let {x, y} = obj.b; in that contrived case. Main thing is, not having as-patterns is not a big deal based on experience with JS1.7+ since 2006 in Mozilla code. /be I've found it quite useful in Clojure/Script and I'm sure folks who have encountered the feature in the ML derived languages would agree. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
David Nolen wrote: On Wed, Apr 18, 2012 at 11:26 AM, Brendan Eich bren...@mozilla.org mailto:bren...@mozilla.org wrote: We've supported destructuring for years and no one has asked for this. I say YAGNI and when in doubt, leave it out. One can always write two destructuring declarations without much repetition: But who has been using it? Certainly not the general JS development community. let {b} = obj; let {x,y} = b; Maybe allowing let {b, b:{x,y}} = obj; would be enough. It sort-of comforms to existing syntax as well as semantics. but of course one would just write let {x, y} = obj.b; in that contrived case. Main thing is, not having as-patterns is not a big deal based on experience with JS1.7+ since 2006 in Mozilla code. /be I've found it quite useful in Clojure/Script and I'm sure folks who have encountered the feature in the ML derived languages would agree. David Herby ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
Clearly it has utility. Same with callable object protocols ;-). The debate is always about whether every useful thing must be included, when there are long-hands aplenty. This cuts both ways, since destructuring is mainly an affordance, syntactic sugar. The other issue here is standardized grammar and parsing algorithm (LR(1) with lookahead and [no LineTerminator here] restrictions). In binding forms we can specialize the pattern sub-grammar and IIRC Allen's draft ES6 spec does. In contrast, for general destructuring assignment expressions, the LHS must be covered by ObjectLiteral or ArrayLiteral. No 'as' in those, but perhaps this just says that 'as', if we add it, is only in the binding forms' pattern sub-grammar. /be David Nolen wrote: On Wed, Apr 18, 2012 at 11:26 AM, Brendan Eich bren...@mozilla.org mailto:bren...@mozilla.org wrote: We've supported destructuring for years and no one has asked for this. I say YAGNI and when in doubt, leave it out. One can always write two destructuring declarations without much repetition: But who has been using it? Certainly not the general JS development community. let {b} = obj; let {x,y} = b; but of course one would just write let {x, y} = obj.b; in that contrived case. Main thing is, not having as-patterns is not a big deal based on experience with JS1.7+ since 2006 in Mozilla code. /be I've found it quite useful in Clojure/Script and I'm sure folks who have encountered the feature in the ML derived languages would agree. David ___ 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: destructuring: as patterns?
Herby Vojčík wrote: Maybe allowing let {b, b:{x,y}} = obj; would be enough. It sort-of comforms to existing syntax as well as semantics. That looks like a mistake. ES5 strict mode and so 1JS wants duplicate property names in object literals to be errors, so I expect the same for duplicate property names in destructuring patterns. Claus's 'as' syntax avoids that problem and could even be shortened: let { b as {x,y} } = obj to bind b, x, and y, instead of what was in the o.p.: let { b: b as {x,y} } = obj DRY and EIBTI argue for 'as' and the shorter shorthand. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
On 18 April 2012 17:51, Herby Vojčík he...@mailbox.sk wrote: Maybe allowing let {b, b:{x,y}} = obj; would be enough. It sort-of comforms to existing syntax as well as semantics. That won't work for arrays, for example. I agree that 'as' patterns (and even more so, wildcard patterns) are basic building blocks that are currently missing. They are extremely useful in practice, for a very small price -- i.e., they are trivial to spec and implement, (unlike callable objects, because Brendan just mentioned those :) ). /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
On Wednesday, 2012-04-18 at 08:26 , Brendan Eich wrote: We've supported destructuring for years and no one has asked for this. I say YAGNI and when in doubt, leave it out. One can always write two destructuring declarations without much repetition: let {b} = obj; let {x,y} = b; but of course one would just write let {x, y} = obj.b; in that contrived case. Main thing is, not having as-patterns is not a big deal based on experience with JS1.7+ since 2006 in Mozilla code. To be honest I've being running into cases where I wished I could match both parent and children in some way. Also, I think that Herby's version is better in fact I had to learn that it's illegal. Unless it's too much of a deal I'd also like following to work: let { a, b, b: { x, y } } = object; /be Claus Reinke wrote: Looking through the destructuring proposal http://wiki.ecmascript.org/doku.php?id=harmony:destructuring there seems to be no mention of 'as' patterns. In typical pattern matching constructs (SML, Haskell, ..), 'as' patterns allow to name a sub-object while continuing the match for its sub-structures. For instance, with var obj = { a: 0, b: { x: 1, y: 2} }; something like let { b: b as {x,y} } = obj would result in the bindings of b to obj.b, x to obj.b.x, y to obj.b.y. This avoids needless repetition when both a subobject and its components need to be extracted. Without 'as', each such case leads to a separate destructuring assignment let { b } = obj let { b: {x,y} } = obj Shouldn't 'as' patterns be included in destructuring? Or have I missed an equivalent feature? Claus ___ es-discuss mailing list es-discuss@mozilla.org (mailto:es-discuss@mozilla.org) https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org (mailto: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: destructuring: as patterns?
Herby Vojčík wrote: Maybe allowing let {b, b:{x,y}} = obj; would be enough. It sort-of comforms to existing syntax as well as semantics. BTW, if you use var instead of let, if already works out of the box (in FF11 firebug console; just tried), so why include as if it already is there, albeit in different form? Herby ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
Another option that feels intuitive to me is: let { a, b: ({ x, y }) } = object; Parentesis imply that I want both parent and matched children. Regards -- Irakli Gozalishvili Web: http://www.jeditoolkit.com/ On Wednesday, 2012-04-18 at 09:01 , Irakli Gozalishvili wrote: On Wednesday, 2012-04-18 at 08:26 , Brendan Eich wrote: We've supported destructuring for years and no one has asked for this. I say YAGNI and when in doubt, leave it out. One can always write two destructuring declarations without much repetition: let {b} = obj; let {x,y} = b; but of course one would just write let {x, y} = obj.b; in that contrived case. Main thing is, not having as-patterns is not a big deal based on experience with JS1.7+ since 2006 in Mozilla code. To be honest I've being running into cases where I wished I could match both parent and children in some way. Also, I think that Herby's version is better in fact I had to learn that it's illegal. Unless it's too much of a deal I'd also like following to work: let { a, b, b: { x, y } } = object; /be Claus Reinke wrote: Looking through the destructuring proposal http://wiki.ecmascript.org/doku.php?id=harmony:destructuring there seems to be no mention of 'as' patterns. In typical pattern matching constructs (SML, Haskell, ..), 'as' patterns allow to name a sub-object while continuing the match for its sub-structures. For instance, with var obj = { a: 0, b: { x: 1, y: 2} }; something like let { b: b as {x,y} } = obj would result in the bindings of b to obj.b, x to obj.b.x, y to obj.b.y. This avoids needless repetition when both a subobject and its components need to be extracted. Without 'as', each such case leads to a separate destructuring assignment let { b } = obj let { b: {x,y} } = obj Shouldn't 'as' patterns be included in destructuring? Or have I missed an equivalent feature? Claus ___ es-discuss mailing list es-discuss@mozilla.org (mailto:es-discuss@mozilla.org) https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org (mailto: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: destructuring: as patterns?
Andreas Rossberg wrote: On 18 April 2012 17:51, Herby Vojčíkhe...@mailbox.sk wrote: Maybe allowing let {b, b:{x,y}} = obj; would be enough. It sort-of comforms to existing syntax as well as semantics. That won't work for arrays, for example. Yeah. :-/ Then either not have it or syntax must be added for it. I'd say use '=' as in assignment: let {b:b={x,y}} = obj; let [a,b={x,y},c] = arr; I agree that 'as' patterns (and even more so, wildcard patterns) are basic building blocks that are currently missing. They are extremely useful in practice, for a very small price -- i.e., they are trivial to spec and implement, (unlike callable objects, because Brendan just mentioned those :) ). /Andreas Herby ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
On Wednesday, 2012-04-18 at 09:02 , Herby Vojčík wrote: Herby Vojčík wrote: Maybe allowing let {b, b:{x,y}} = obj; would be enough. It sort-of comforms to existing syntax as well as semantics. BTW, if you use var instead of let, if already works out of the box (in FF11 firebug console; just tried), so why include as if it already is there, albeit in different form? OMG, you're right!!! I could swear it did not worked before as I had unsuccessful attempts to use that form. I guess it's ok if Brendan did not knew it either :D Herby ___ es-discuss mailing list es-discuss@mozilla.org (mailto: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: destructuring: as patterns?
On 18 April 2012 18:09, Herby Vojčík he...@mailbox.sk wrote: Andreas Rossberg wrote: On 18 April 2012 17:51, Herby Vojčíkhe...@mailbox.sk wrote: Maybe allowing let {b, b:{x,y}} = obj; would be enough. It sort-of comforms to existing syntax as well as semantics. That won't work for arrays, for example. Yeah. :-/ Argument lists are the more interesting case, btw. Layering has to be an independent and compositional construct. Then either not have it or syntax must be added for it. I'd say use '=' as in assignment: let {b:b={x,y}} = obj; let [a,b={x,y},c] = arr; Unfortunately, that's already taken for default values, 'as' probably is as good as you can get. /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
Herby Vojčík wrote: Herby Vojčík wrote: Maybe allowing let {b, b:{x,y}} = obj; would be enough. It sort-of comforms to existing syntax as well as semantics. BTW, if you use var instead of let, if already works out of the box (in FF11 firebug console; just tried), so why include as if it already is there, albeit in different form? We implemented destructuring years ago to implementor- and user-test ES4 proposals. They did not forbid duplicates. That's all. Nothing normative in experimental Firefox implementation features, of course. You cite them as already [there] and that's true but it doesn't govern what goes into ES6. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
Irakli Gozalishvili wrote: OMG, you're right!!! I could swear it did not worked before as I had unsuccessful attempts to use that form. I guess it's ok if Brendan did not knew it either :D I never said I didn't know, I said ES6 new syntax opts into strict mode for things like banning duplicate property names in object literals, so this might well apply to duplicate property names in object patterns. I still think this may be the case. ES4-era destructuring was very shallow sugar: var {x: y} = z; = var y = z.x; and so on -- with a temporary to avoid evaluating z more than once, and z is evaluated first (a left-to-right evaluation order break, but others exist, e.g. for-in loop head evaluation order). /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
On Apr 18, 2012, at 9:29 AM, Brendan Eich wrote: Herby Vojčík wrote: Herby Vojčík wrote: Maybe allowing let {b, b:{x,y}} = obj; would be enough. It sort-of comforms to existing syntax as well as semantics. BTW, if you use var instead of let, if already works out of the box (in FF11 firebug console; just tried), so why include as if it already is there, albeit in different form? We implemented destructuring years ago to implementor- and user-test ES4 proposals. They did not forbid duplicates. That's all. Nothing normative in experimental Firefox implementation features, of course. You cite them as already [there] and that's true but it doesn't govern what goes into ES6. But is also works this way according to the ES6 draft spec. It works with var because var allows duplicated declarations: var a=1; var a=2; var a=3; which, from a declaration perspective isn't really any different from var a=1,a=2,a=3; However let/const does not: { //block level duplicate declaration early error let b=1; let b=2; } or just let b=1,b=2 ; //block level duplicate declaration error var {b,b:{x,y}} = obj; //fine because var declaration static semantics don't disallow duplicates { //avoid any conflicts with the preceeding var let {b,b:{x,y}} = obj; //block level duplicate declaration } You might argue that the second b in the destructuring isn't actually introducing a binding for b. However, syntactically it looks like one and that is what the static semantic rule is driven off of. If we allow that, we would also be allowing: let b=somethingElse; let {b:{x,y})=obj; If we want to allow that I'll have to some up with a different way to specify the static semantics. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
I've found it quite useful in Clojure/Script and I'm sure folks who have encountered the feature in the ML derived languages would agree. Indeed, all of the pattern-match-supporting functional languages I've used also supported 'as'-patterns in some form ('var@pat' in Haskell, 'var as pat' in SML and variants, 'pat=pat' in Erlang, 'as pat var' in (little-known) KiR). Those constructs are hard to search for on github (too many false matches, though searching for 'as' in Standard ML code might work), but I find them both useful and popular. Some of the usefulness comes from using pattern matching as a structural guard (checking the substructure conforms to a pattern, then just naming the substructure wholesale). I have no experience with a language that only destructures, without matching, but I would expect to use as-patterns with destructuring as well, increasingly so with upcoming language constructs. The main problems seem to be cover-grammars (construct should be valid expression and pattern), and that the obvious choice '=' is already taken for default parameters. A common generalization of as-patterns are conjunctive patterns (as in Successor ML or Erlang), which suggests 'patpat' or perhaps '(pat,pat)' as alternative syntax. Claus ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
Irakli Gozalishvili wrote: I'm sorry for inappropriate comment. No worries! My citing Mozilla's experimental JS1.7+ implementation/user-testing experience is informative, not nearly definitive or anywhere near normative; somewhat convincing when something is popular, best when we learned from a negative result that's clear (no confounders). /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
Allen Wirfs-Brock wrote: On Apr 18, 2012, at 9:29 AM, Brendan Eich wrote: Herby Vojčík wrote: Herby Vojčík wrote: Maybe allowing let {b, b:{x,y}} = obj; would be enough. It sort-of comforms to existing syntax as well as semantics. BTW, if you use var instead of let, if already works out of the box (in FF11 firebug console; just tried), so why include as if it already is there, albeit in different form? We implemented destructuring years ago to implementor- and user-test ES4 proposals. They did not forbid duplicates. That's all. Nothing normative in experimental Firefox implementation features, of course. You cite them as already [there] and that's true but it doesn't govern what goes into ES6. But is also works this way according to the ES6 draft spec. It works with var because var allows duplicated declarations: var a=1; var a=2; var a=3; which, from a declaration perspective isn't really any different from var a=1,a=2,a=3; However let/const does not: { //block level duplicate declaration early error let b=1; let b=2; } or just let b=1,b=2 ; //block level duplicate declaration error var {b,b:{x,y}} = obj; //fine because var declaration static semantics don't disallow duplicates { //avoid any conflicts with the preceeding var let {b,b:{x,y}} = obj; //block level duplicate declaration } But the 'let {b:b, b:{x,y}}' is different beast, it is: { let b = {x:1,y:2}; let {x,y} = {x:1,y:2}; } and there is, imo, no conflict in this. You might argue that the second b in the destructuring isn't actually introducing a binding for b. However, syntactically it looks like one and that is what the static semantic rule is driven off of. If we allow that, we would also be allowing: let b=somethingElse; let {b:{x,y})=obj; If we want to allow that I'll have to some up with a different way to But, AFAICT, this should be allowed. The 'b:' from destructuring is different from 'b' from let. Is the previous code disallowed in current state? specify the static semantics. Allen Herby ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
Herby Vojčík wrote: But, AFAICT, this should be allowed. The 'b:' from destructuring is Sorry for caps, I don't know why I write it that way... I somehow automatically held shift because it is an acronym, probably. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
On Apr 18, 2012, at 9:49 AM, Allen Wirfs-Brock wrote: ... var {b,b:{x,y}} = obj; //fine because var declaration static semantics don't disallow duplicates { //avoid any conflicts with the preceeding var let {b,b:{x,y}} = obj; //block level duplicate declaration } You might argue that the second b in the destructuring isn't actually introducing a binding for b. However, syntactically it looks like one and that is what the static semantic rule is driven off of. If we allow that, we would also be allowing: let b=somethingElse; let {b:{x,y})=obj; If we want to allow that I'll have to some up with a different way to specify the static semantics. False alarm! Actually the above isn't correct. The current spec draft actually does allow let {b,b:{x,y}}; but would issue an early error on let {b,b:{x:b,y}}; It is all in the static semantics production Bound Names in 12.2.4 The BoundNames of let {b}=obj is [b] The BoundNames of let {b:x} = obj is [x] The Bound Names of let {b,b:{x,y} is [b,x,y] The Bound Names of let {b,b:{x:b,y}}; is [b,b,y] and produces a duplicate declaration early error. For a var declaration it would be allowd. Sorry for the confusion. I should have read my own spec. more carefully. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
On Apr 18, 2012, at 10:59 AM, Herby Vojčík wrote: ... But, AFAICT, this should be allowed. The 'b:' from destructuring is different from 'b' from let. Is the previous code disallowed in current state? You're right, I was wrong. See my followup response. Thanks, Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
Allen Wirfs-Brock wrote: False alarm! Actually the above isn't correct. The current spec draft actually does allow let {b,b:{x,y}}; Nice -- is this sufficient to avoid 'as'? For array patterns we would need to allow property assignments in array literals: let [b, 0:{x,y}]; This was proposed at one point, IIRC, but a while ago. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
On Apr 18, 2012, at 11:42 AM, Brendan Eich wrote: Allen Wirfs-Brock wrote: False alarm! Actually the above isn't correct. The current spec draft actually does allow let {b,b:{x,y}}; Nice -- is this sufficient to avoid 'as'? For array patterns we would need to allow property assignments in array literals: let [b, 0:{x,y}]; This was proposed at one point, IIRC, but a while ago. It was also suggested that we allow iterators/generators to supply the initialization values to array destructurings. This currently isn't in the draft spec. and I think it would introduce some fairly significant specification and practical complications (eg, rest bindings and open-ended generators). However, the reason I bring it up it that if we ever do want to add that sort of generative initialization value feature, it would seem to have significant interactions with the explicit array property designator feature shown above. The most future proof thing for right now would be to do neither. Allen /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
Allen Wirfs-Brock wrote: For array patterns we would need to allow property assignments in array literals: let [b, 0:{x,y}] = ...; This was proposed at one point, IIRC, but a while ago. Of course, one could destructure like so: let {0: b, 0: {x, y}} = ...; It was also suggested that we allow iterators/generators to supply the initialization values to array destructurings. This currently isn't in the draft spec. and I think it would introduce some fairly significant specification and practical complications (eg, rest bindings and open-ended generators). Destructuring patterns should be static. I don't see a conflict if we stick to this rule, but given the ability to use an object pattern, I don't see a need for the array literal element label syntax either. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
Brendan Eich wrote: Allen Wirfs-Brock wrote: For array patterns we would need to allow property assignments in array literals: let [b, 0:{x,y}] = ...; This was proposed at one point, IIRC, but a while ago. Of course, one could destructure like so: let {0: b, 0: {x, y}} = ...; It was also suggested that we allow iterators/generators to supply the initialization values to array destructurings. This currently isn't in the draft spec. and I think it would introduce some fairly significant specification and practical complications (eg, rest bindings and open-ended generators). Destructuring patterns should be static. I don't see a conflict if we stick to this rule, but given the ability to use an object pattern, I don't see a need for the array literal element label syntax either. As was already pointed out, problems are not only _array_ destructurings, but more argument list destructrings, where if you want to destructure 0-th argument both as b and as {x,y}, you would need something like that, since you already are inside list, you cannot opt for object. (but if it is not the problem, I'd gladly see at least the object double-destructure-same-field in ES6. It is not violating the no double property names of strict mode since the assignment goes the other way) /be Herby ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
Herby Vojčík wrote: As was already pointed out, problems are not only _array_ destructurings, but more argument list destructrings, where if you want to destructure 0-th argument both as b and as {x,y}, you would need something like that, since you already are inside list, you cannot opt for object. Why can't you use an object pattern? Array pattern is just shorthand for object pattern. (but if it is not the problem, I'd gladly see at least the object double-destructure-same-field in ES6. It is not violating the no double property names of strict mode since the assignment goes the other way) Yes, Allen covered this five messages back in the thread. There's no problem because the set of bindings has no dups. Destructuring as dual of object or array literals threw me (even me, a big fan of duality -- but only briefly ;-). /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
Brendan Eich wrote: Herby Vojčík wrote: As was already pointed out, problems are not only _array_ destructurings, but more argument list destructrings, where if you want to destructure 0-th argument both as b and as {x,y}, you would need something like that, since you already are inside list, you cannot opt for object. Why can't you use an object pattern? Array pattern is just shorthand for object pattern. Not implicitly, not inside the argument list itself. You would need to write function foo (...args) { let {0:b, 0:{x,y}, foo, bar, baz} = args; ... } but between 'foo (' and ') {' you must play by the rules of array destructuring, where '0:' is not allowed. /be Herby ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
On Apr 18, 2012, at 1:45 PM, Herby Vojčík wrote: Brendan Eich wrote: Allen Wirfs-Brock wrote: For array patterns we would need to allow property assignments in array literals: let [b, 0:{x,y}] = ...; This was proposed at one point, IIRC, but a while ago. Of course, one could destructure like so: let {0: b, 0: {x, y}} = ...; It was also suggested that we allow iterators/generators to supply the initialization values to array destructurings. This currently isn't in the draft spec. and I think it would introduce some fairly significant specification and practical complications (eg, rest bindings and open-ended generators). Destructuring patterns should be static. I don't see a conflict if we stick to this rule, but given the ability to use an object pattern, I don't see a need for the array literal element label syntax either. As was already pointed out, problems are not only _array_ destructurings, but more argument list destructrings, where if you want to destructure 0-th argument both as b and as {x,y}, you would need something like that, since you already are inside list, you cannot opt for object. function f({b},...rest) { let {x,y}=b; ... } doesn't seem like too much of a burden (but if it is not the problem, I'd gladly see at least the object double-destructure-same-field in ES6. It is not violating the no double property names of strict mode since the assignment goes the other way) It's in the spec. draft. There aren't actually object literals so the duplicate property name rules don't apply. It's the duplicate lexical binding rules that are in play, but only on the target names, not the property selectors. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
Herby Vojčík wrote: function foo (...args) { let {0:b, 0:{x,y}, foo, bar, baz} = args; ... } That's not right, if you go the long way round you want: function foo (...args) { let {0:b, 0:{x,y}, 1:foo, 2:bar, 3:baz} = args; ... } but as Allen just suggested, the right way to do it is: function foo ({b}, ...args) { let {x,y} = b; let [foo, bar, baz] = args; ... } /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
Agreed. This is easy to spec and implement, highly composable (it fits neatly into the algebra of destructuring patterns everywhere, as opposed to just in object property-name positions), has no problems with side effects, and does not violate restrictions that IINM strict mode is supposed to ban (repeated property names in literals). The repeated property-name thing is a hack. It does not Say What You Mean (it's a total surprise). It is not composable (it only works for property names, not for array indices). Worst of all, it will trigger getters twice: let { b, b: { x, y } } = { get b() { console.log(BOO!); return 17 } } BOO! BOO! But if that's the only way to do it, then if you want to destructure a getter, you will be forced not to use the hack, and to bind a temporary variable and do a second destructuring on a second line. *Please*, let's do this right. There's no reason to introduce hacks. I'm open to various syntaxes, but I think `as` is nice especially because it could work well for import/export syntax too. Lots of people complain about confusion over which is the bound name and which is the label. IINM, we could allow both: let { x: x as y } = obj; and let { x as y } = obj; which would be a nice idiom for making it more obvious that x is the label and y is the binding. Then this would be especially nice for imports: import { x as y } from X; Dave On Apr 18, 2012, at 8:57 AM, Andreas Rossberg wrote: On 18 April 2012 17:51, Herby Vojčík he...@mailbox.sk wrote: Maybe allowing let {b, b:{x,y}} = obj; would be enough. It sort-of comforms to existing syntax as well as semantics. That won't work for arrays, for example. I agree that 'as' patterns (and even more so, wildcard patterns) are basic building blocks that are currently missing. They are extremely useful in practice, for a very small price -- i.e., they are trivial to spec and implement, (unlike callable objects, because Brendan just mentioned those :) ). /Andreas ___ 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: destructuring: as patterns?
On Wed, Apr 18, 2012 at 5:35 PM, David Herman dher...@mozilla.com wrote: Agreed. This is easy to spec and implement, highly composable (it fits neatly into the algebra of destructuring patterns everywhere, as opposed to just in object property-name positions), has no problems with side effects, and does not violate restrictions that IINM strict mode is supposed to ban (repeated property names in literals). The repeated property-name thing is a hack. It does not Say What You Mean (it's a total surprise). It is not composable (it only works for property names, not for array indices). Worst of all, it will trigger getters twice: let { b, b: { x, y } } = { get b() { console.log(BOO!); return 17 } } BOO! BOO! But if that's the only way to do it, then if you want to destructure a getter, you will be forced not to use the hack, and to bind a temporary variable and do a second destructuring on a second line. *Please*, let's do this right. There's no reason to introduce hacks. I'm open to various syntaxes, but I think `as` is nice especially because it could work well for import/export syntax too. Lots of people complain about confusion over which is the bound name and which is the label. IINM, we could allow both: let { x: x as y } = obj; and let { x as y } = obj; which would be a nice idiom for making it more obvious that x is the label and y is the binding. Then this would be especially nice for imports: import { x as y } from X; Dave +1 ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
David Herman wrote: *Please*, let's do this right. This says to me (what I originally expected) that duplicate property name at any ply in an object pattern should be an early error. Anyone disagree? /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
On Apr 18, 2012, at 2:48 PM, Brendan Eich wrote: David Herman wrote: *Please*, let's do this right. This says to me (what I originally expected) that duplicate property name at any ply in an object pattern should be an early error. Anyone disagree? I'm not sure that the concern about repeated side-effects is very significant given that any property access can have arbitrary side-effects including adding and removing properties from the RHS object. Regardless, making duplicate property names an early error is easy enough and seems to eliminate a potential point of confusion. I'm not necessarily sold on as yet. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss