an idea for replacing arguments.length
One of the the few remaining uses of a function's 'arguments' binding is to determine the actual number of passed arguments. This is necessary in some overloading scenarios where a function has different behavior when an argument is completely absent then it has when undefined (or any other default value) is explicitly passed in that parameter position. That situation occurs in a number of DOM APIs and even a few ES library functions. For example(see https://bugs.ecmascript.org/show_bug.cgi?id=1877 ), Array.prototype.splice returns different results for: [1,2,3].splice() and [1,2,3].splice(undefined) The natural ES6 declaration for a splice function is: function splice(start, deleteCount, ...items) {... but if you write it this way then within the body you have to have a test like: if (arguments.length == 0) {... to implement the correct web-compatable behavior. Or, alternatively you could declare the functions as: function splice(...actualArgs) { let [start, stop, ...item] = actualArgs; ... if (actualArgs.length == 0) {... So, to implement a Web-compaable version of splice you either have to use 'arguments' to determine the actual number of passed objects or you need to declare it with a bogus parameter pattern and use explicit or implicit destructuring to parse out the positional parameters. One way around this dilemma would be to provide a syntactic affordance for determing the actual argument count. For example, one possibility would be to allow the last item of any formal parameter list to be an item of the syntactic form: ActualArgumentCount : '#' BindingIdentifier So, the declaration for splice could then be: function splice(start, deleteCount, ...items, #argCount) { ... if (argCount == 0) {... Thoughts? Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
optional yield expression creates ambiguity
see bug: https://bugs.ecmascript.org/show_bug.cgi?id=2011 The decision to make the AssignmentExpression optional within a YieldExpression creates an ambiguity when combined with class declarations. For example cosider: function *gen() { class Foo extends yield {} { } } Is the intent for a yield expression that yields a new object or a a yield expression with yields a implicit undefined. Neither a human nor a parser can know for use what the authors actual intent was. There are several ways we could fix this problem: 1) Retract the decision to make the yield assignment expression optional. In this case a 'yield', in all yield expression contexts, would have to always be followed by an explicit expression producing the value to yield. 2) Make the use of 'yield' illegal in the 'extends' clause of class declarations. Arguably this is comparable to the restrictions on the use of 'in' within for-in statements. This would probably not be a major usage issue as actual use cases of 'yield' in that context seems quite implausible. 3) Continue to allow usage of 'yield' expressions in 'extends' clauses but make the AssignmentExpression part of the YieldExpression mandatory in that context. 4) some other, even more ad hoc, disambiguation rule. Either #1 or #2 would be trivial to specify. #2 would be a straight forward use of an expression grammar parameter that we already have. #3 is somewhat harder to specify and requires a new parameter on all of the expression grammar productions. It would require more editorial work to implement and result in a more cluttered grammar definitions. #4 needs an actual proposal that can be evaluated. I would be happy with either alternative #1 or #2. The actual utility of a YieldExpression in an 'extends' clause seems so low that I don't think we should make the entire expression grammar more complicated just to support alternative #3. Thoughts? Allen___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
1) # is one of the few ascii characters we haven't used up yet. Let's not use it up on a minor convenience. 2) Introducing new syntax for use cases that are expected to be frequent, e.g., classes, often pays for its weight. The frequency makes it likely that readers will understand what it is the vast majority of times they encounter it. New syntax that gets used once in a blue moon can only be justified if the pain of doing without in those blue-moon cases is huge. In this case, it isn't. For those rare occasions when they see it, readers are much more likely to guess what arguments.length mean that this funny newfangled # thing. Code is read much more often than it is written -- at least code that matters. Brevity is useful as a metric only to the degree that it serves as a proxy for cognitive load on the reader. On Sun, Nov 10, 2013 at 10:12 AM, Allen Wirfs-Brock al...@wirfs-brock.comwrote: One of the the few remaining uses of a function's 'arguments' binding is to determine the actual number of passed arguments. This is necessary in some overloading scenarios where a function has different behavior when an argument is completely absent then it has when undefined (or any other default value) is explicitly passed in that parameter position. That situation occurs in a number of DOM APIs and even a few ES library functions. For example(see https://bugs.ecmascript.org/show_bug.cgi?id=1877 ), Array.prototype.splice returns different results for: [1,2,3].splice() and [1,2,3].splice(undefined) The natural ES6 declaration for a splice function is: function splice(start, deleteCount, ...items) {... but if you write it this way then within the body you have to have a test like: if (arguments.length == 0) {... to implement the correct web-compatable behavior. Or, alternatively you could declare the functions as: function splice(...actualArgs) { let [start, stop, ...item] = actualArgs; ... if (actualArgs.length == 0) {... So, to implement a Web-compaable version of splice you either have to use 'arguments' to determine the actual number of passed objects or you need to declare it with a bogus parameter pattern and use explicit or implicit destructuring to parse out the positional parameters. One way around this dilemma would be to provide a syntactic affordance for determing the actual argument count. For example, one possibility would be to allow the last item of any formal parameter list to be an item of the syntactic form: ActualArgumentCount : '#' BindingIdentifier So, the declaration for splice could then be: function splice(start, deleteCount, ...items, #argCount) { ... if (argCount == 0) {... Thoughts? Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
Interesting, unless we haven't `...rest` already. Otherwise, sounds as an overhead (and really just a workaround to fix a particular issue, but not a very useful language construct) to me. Since in the ES6 world, if a function is designed to work with variant number of arguments, this should (naturally) be done via `...rest` arguments. The overhead is: `(...args, #argsCount) = {}`: in this case `args.length` and `#argsCount` do the same, that increases the ways of doing two the same things with different approaches (not the best of way). So yeah, I'd assume the second way of implementation in your example (with destructing or whatever) as a more natural and straightforward. Dmitry On Sunday, November 10, 2013, Allen Wirfs-Brock wrote: One of the the few remaining uses of a function's 'arguments' binding is to determine the actual number of passed arguments. This is necessary in some overloading scenarios where a function has different behavior when an argument is completely absent then it has when undefined (or any other default value) is explicitly passed in that parameter position. That situation occurs in a number of DOM APIs and even a few ES library functions. For example(see https://bugs.ecmascript.org/show_bug.cgi?id=1877 ), Array.prototype.splice returns different results for: [1,2,3].splice() and [1,2,3].splice(undefined) The natural ES6 declaration for a splice function is: function splice(start, deleteCount, ...items) {... but if you write it this way then within the body you have to have a test like: if (arguments.length == 0) {... to implement the correct web-compatable behavior. Or, alternatively you could declare the functions as: function splice(...actualArgs) { let [start, stop, ...item] = actualArgs; ... if (actualArgs.length == 0) {... So, to implement a Web-compaable version of splice you either have to use 'arguments' to determine the actual number of passed objects or you need to declare it with a bogus parameter pattern and use explicit or implicit destructuring to parse out the positional parameters. One way around this dilemma would be to provide a syntactic affordance for determing the actual argument count. For example, one possibility would be to allow the last item of any formal parameter list to be an item of the syntactic form: ActualArgumentCount : '#' BindingIdentifier So, the declaration for splice could then be: function splice(start, deleteCount, ...items, #argCount) { ... if (argCount == 0) {... Thoughts? Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: optional yield expression creates ambiguity
On Sun, Nov 10, 2013 at 1:46 PM, Allen Wirfs-Brock al...@wirfs-brock.com wrote: The actual utility of a YieldExpression in an 'extends' clause seems so low that I don't think we should make the entire expression grammar more complicated just to support alternative #3. It would be possible to just parenthesize the YieldExpression if you actually wanted one in an extends clause, right? Sam ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
On the other hand, we are this close in ES6 to relieveing people from having to use arguments at all. I like the intention behind Allen's idea. To defend the concrete syntax a bit, one would argue that only the final formal parameter may be prefixed with #, and we are free to use # in other ways elsewhere. If # should be kept reserved even in this context, then perhaps something like function f(args: x, y, z) { // use x, y, z freely (they could be patterns) switch (args.length) { case 1: ... case 2: ... // etc. } } The label names a rest parameter for the entire parameter list. /be Mark S. Miller mailto:erig...@google.com November 10, 2013 6:52 PM 1) # is one of the few ascii characters we haven't used up yet. Let's not use it up on a minor convenience. 2) Introducing new syntax for use cases that are expected to be frequent, e.g., classes, often pays for its weight. The frequency makes it likely that readers will understand what it is the vast majority of times they encounter it. New syntax that gets used once in a blue moon can only be justified if the pain of doing without in those blue-moon cases is huge. In this case, it isn't. For those rare occasions when they see it, readers are much more likely to guess what arguments.length mean that this funny newfangled # thing. Code is read much more often than it is written -- at least code that matters. Brevity is useful as a metric only to the degree that it serves as a proxy for cognitive load on the reader. -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss Allen Wirfs-Brock mailto:al...@wirfs-brock.com November 10, 2013 7:12 PM One of the the few remaining uses of a function's 'arguments' binding is to determine the actual number of passed arguments. This is necessary in some overloading scenarios where a function has different behavior when an argument is completely absent then it has when undefined (or any other default value) is explicitly passed in that parameter position. That situation occurs in a number of DOM APIs and even a few ES library functions. For example(see https://bugs.ecmascript.org/show_bug.cgi?id=1877 ), Array.prototype.splice returns different results for: [1,2,3].splice() and [1,2,3].splice(undefined) The natural ES6 declaration for a splice function is: function splice(start, deleteCount, ...items) {... but if you write it this way then within the body you have to have a test like: if (arguments.length == 0) {... to implement the correct web-compatable behavior. Or, alternatively you could declare the functions as: function splice(...actualArgs) { let [start, stop, ...item] = actualArgs; ... if (actualArgs.length == 0) {... So, to implement a Web-compaable version of splice you either have to use 'arguments' to determine the actual number of passed objects or you need to declare it with a bogus parameter pattern and use explicit or implicit destructuring to parse out the positional parameters. One way around this dilemma would be to provide a syntactic affordance for determing the actual argument count. For example, one possibility would be to allow the last item of any formal parameter list to be an item of the syntactic form: ActualArgumentCount : '#' BindingIdentifier So, the declaration for splice could then be: function splice(start, deleteCount, ...items, #argCount) { ... if (argCount == 0) {... Thoughts? Allen ___ 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: optional yield expression creates ambiguity
yes On Nov 10, 2013, at 11:04 AM, Sam Tobin-Hochstadt wrote: On Sun, Nov 10, 2013 at 1:46 PM, Allen Wirfs-Brock al...@wirfs-brock.com wrote: The actual utility of a YieldExpression in an 'extends' clause seems so low that I don't think we should make the entire expression grammar more complicated just to support alternative #3. It would be possible to just parenthesize the YieldExpression if you actually wanted one in an extends clause, right? Sam ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
On Nov 10, 2013, at 10:52 AM, Mark S. Miller wrote: 1) # is one of the few ascii characters we haven't used up yet. Let's not use it up on a minor convenience. But this is a very restrictive context. It isn't clear that it would impact any other possible usage. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
On Nov 10, 2013, at 11:08 AM, Brendan Eich wrote: On the other hand, we are this close in ES6 to relieveing people from having to use arguments at all. I like the intention behind Allen's idea. To defend the concrete syntax a bit, one would argue that only the final formal parameter may be prefixed with #, and we are free to use # in other ways elsewhere. If # should be kept reserved even in this context, then perhaps something like The use of : suggests that another alternative could be: function splice(start, deleteCount, ...items, :argCount) { but I still lie # better and don't think this usage would have to impact any other possbile use of that character. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
Le 10/11/2013 19:12, Allen Wirfs-Brock a écrit : One of the the few remaining uses of a function's 'arguments' binding is to determine the actual number of passed arguments. This is necessary in some overloading scenarios where a function has different behavior when an argument is completely absent then it has when undefined (or any other default value) is explicitly passed in that parameter position. That situation occurs in a number of DOM APIs and even a few ES library functions. For example(see https://bugs.ecmascript.org/show_bug.cgi?id=1877 ), Array.prototype.splice returns different results for: [1,2,3].splice() and [1,2,3].splice(undefined) The natural ES6 declaration for a splice function is: function splice(start, deleteCount, ...items) {... but if you write it this way then within the body you have to have a test like: if (arguments.length == 0) {... to implement the correct web-compatable behavior. Or, alternatively you could declare the functions as: function splice(...actualArgs) { let [start, stop, ...item] = actualArgs; ... if (actualArgs.length == 0) {... So, to implement a Web-compaable version of splice you either have to use 'arguments' to determine the actual number of passed objects or you need to declare it with a bogus parameter pattern and use explicit or implicit destructuring to parse out the positional parameters. I imagine it also breaks splice.length, but that's fixed by making length configurable (writable? I don't remember). I'm fine with the second solution. It's inelegant, but it's also legacy... I don't think differenciating .splice() and .splice(undefined) and equivalent use cases is a practice that should be encouraged. One way around this dilemma would be to provide a syntactic affordance for determing the actual argument count. For example, one possibility would be to allow the last item of any formal parameter list to be an item of the syntactic form: ActualArgumentCount : '#' BindingIdentifier So, the declaration for splice could then be: function splice(start, deleteCount, ...items, #argCount) { ... if (argCount == 0) {... Thoughts? Why creating something new if it's only encouraging a bad practice? Is there a good use case? David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
RE: an idea for replacing arguments.length
From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of David Bruant Why creating something new if it's only encouraging a bad practice? Is there a good use case? +1. I thought we were trying to make `undefined` and not passed equivalent. Adding a feature specifically designed to bypass this seems unfortunate, especially since we already have an ugly feature (`arguments.length`) for doing such an ugly thing. On the other hand, Brendan's proposal seems pretty neat. I am pretty sure that while writing some Traceur code I wanted something similar. But even then, I suppose I would want `args` in his example to always have length `3`, so as to discourage the bad practice. I.e. `f(1)` would give `args` as `[1, undefined, undefined]`. It would be a way of reifying arguments for the ES6 era, where differences between not-passed and `undefined` are minimized, and of course it would be a real array. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
Hi Brendan and Allen, you are both responding only to my point #1. I consider my point #2 --- cognitive load of the reader on encountering a rarely seen construct --- to be the more significant criticism here. On these grounds, your function f(args: x, y, z) { is worse. Given how : is already used in JS, this suggests that args is either a label name, which the more astute reader can easily disqualify, or a property name, suggesting some shorthand for named parameters. Note that I am not saying that the meanings of all syntactic constructs have to be guessable with no guidance. But the rarely used ones do. 3) Awkward syntax for some rarely used cases is the price of good syntax for common cases. On Sun, Nov 10, 2013 at 11:08 AM, Brendan Eich bren...@mozilla.com wrote: On the other hand, we are this close in ES6 to relieveing people from having to use arguments at all. I like the intention behind Allen's idea. To defend the concrete syntax a bit, one would argue that only the final formal parameter may be prefixed with #, and we are free to use # in other ways elsewhere. If # should be kept reserved even in this context, then perhaps something like function f(args: x, y, z) { // use x, y, z freely (they could be patterns) switch (args.length) { case 1: ... case 2: ... // etc. } } The label names a rest parameter for the entire parameter list. /be Mark S. Miller mailto:erig...@google.com November 10, 2013 6:52 PM 1) # is one of the few ascii characters we haven't used up yet. Let's not use it up on a minor convenience. 2) Introducing new syntax for use cases that are expected to be frequent, e.g., classes, often pays for its weight. The frequency makes it likely that readers will understand what it is the vast majority of times they encounter it. New syntax that gets used once in a blue moon can only be justified if the pain of doing without in those blue-moon cases is huge. In this case, it isn't. For those rare occasions when they see it, readers are much more likely to guess what arguments.length mean that this funny newfangled # thing. Code is read much more often than it is written -- at least code that matters. Brevity is useful as a metric only to the degree that it serves as a proxy for cognitive load on the reader. -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss Allen Wirfs-Brock mailto:al...@wirfs-brock.com November 10, 2013 7:12 PM One of the the few remaining uses of a function's 'arguments' binding is to determine the actual number of passed arguments. This is necessary in some overloading scenarios where a function has different behavior when an argument is completely absent then it has when undefined (or any other default value) is explicitly passed in that parameter position. That situation occurs in a number of DOM APIs and even a few ES library functions. For example(see https://bugs.ecmascript.org/show_bug.cgi?id=1877 ), Array.prototype.splice returns different results for: [1,2,3].splice() and [1,2,3].splice(undefined) The natural ES6 declaration for a splice function is: function splice(start, deleteCount, ...items) {... but if you write it this way then within the body you have to have a test like: if (arguments.length == 0) {... to implement the correct web-compatable behavior. Or, alternatively you could declare the functions as: function splice(...actualArgs) { let [start, stop, ...item] = actualArgs; ... if (actualArgs.length == 0) {... So, to implement a Web-compaable version of splice you either have to use 'arguments' to determine the actual number of passed objects or you need to declare it with a bogus parameter pattern and use explicit or implicit destructuring to parse out the positional parameters. One way around this dilemma would be to provide a syntactic affordance for determing the actual argument count. For example, one possibility would be to allow the last item of any formal parameter list to be an item of the syntactic form: ActualArgumentCount : '#' BindingIdentifier So, the declaration for splice could then be: function splice(start, deleteCount, ...items, #argCount) { ... if (argCount == 0) {... Thoughts? Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
Also function f(args: x, y, z) { will suggest to TypeScript readers that the parameter args has type x. On Sun, Nov 10, 2013 at 11:44 AM, Mark S. Miller erig...@google.com wrote: Hi Brendan and Allen, you are both responding only to my point #1. I consider my point #2 --- cognitive load of the reader on encountering a rarely seen construct --- to be the more significant criticism here. On these grounds, your function f(args: x, y, z) { is worse. Given how : is already used in JS, this suggests that args is either a label name, which the more astute reader can easily disqualify, or a property name, suggesting some shorthand for named parameters. Note that I am not saying that the meanings of all syntactic constructs have to be guessable with no guidance. But the rarely used ones do. 3) Awkward syntax for some rarely used cases is the price of good syntax for common cases. On Sun, Nov 10, 2013 at 11:08 AM, Brendan Eich bren...@mozilla.comwrote: On the other hand, we are this close in ES6 to relieveing people from having to use arguments at all. I like the intention behind Allen's idea. To defend the concrete syntax a bit, one would argue that only the final formal parameter may be prefixed with #, and we are free to use # in other ways elsewhere. If # should be kept reserved even in this context, then perhaps something like function f(args: x, y, z) { // use x, y, z freely (they could be patterns) switch (args.length) { case 1: ... case 2: ... // etc. } } The label names a rest parameter for the entire parameter list. /be Mark S. Miller mailto:erig...@google.com November 10, 2013 6:52 PM 1) # is one of the few ascii characters we haven't used up yet. Let's not use it up on a minor convenience. 2) Introducing new syntax for use cases that are expected to be frequent, e.g., classes, often pays for its weight. The frequency makes it likely that readers will understand what it is the vast majority of times they encounter it. New syntax that gets used once in a blue moon can only be justified if the pain of doing without in those blue-moon cases is huge. In this case, it isn't. For those rare occasions when they see it, readers are much more likely to guess what arguments.length mean that this funny newfangled # thing. Code is read much more often than it is written -- at least code that matters. Brevity is useful as a metric only to the degree that it serves as a proxy for cognitive load on the reader. -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss Allen Wirfs-Brock mailto:al...@wirfs-brock.com November 10, 2013 7:12 PM One of the the few remaining uses of a function's 'arguments' binding is to determine the actual number of passed arguments. This is necessary in some overloading scenarios where a function has different behavior when an argument is completely absent then it has when undefined (or any other default value) is explicitly passed in that parameter position. That situation occurs in a number of DOM APIs and even a few ES library functions. For example(see https://bugs.ecmascript.org/show_bug.cgi?id=1877 ), Array.prototype.splice returns different results for: [1,2,3].splice() and [1,2,3].splice(undefined) The natural ES6 declaration for a splice function is: function splice(start, deleteCount, ...items) {... but if you write it this way then within the body you have to have a test like: if (arguments.length == 0) {... to implement the correct web-compatable behavior. Or, alternatively you could declare the functions as: function splice(...actualArgs) { let [start, stop, ...item] = actualArgs; ... if (actualArgs.length == 0) {... So, to implement a Web-compaable version of splice you either have to use 'arguments' to determine the actual number of passed objects or you need to declare it with a bogus parameter pattern and use explicit or implicit destructuring to parse out the positional parameters. One way around this dilemma would be to provide a syntactic affordance for determing the actual argument count. For example, one possibility would be to allow the last item of any formal parameter list to be an item of the syntactic form: ActualArgumentCount : '#' BindingIdentifier So, the declaration for splice could then be: function splice(start, deleteCount, ...items, #argCount) { ... if (argCount == 0) {... Thoughts? Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- Cheers, --MarkM -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org
Re: an idea for replacing arguments.length
I would rather think about a smart syntax able to tell the function it should expose arguments as it was before. `function splice:arguments(start, deleteCount, ...items)` or `function splice:args(start, deleteCount, ...items)` or anything different that looks reasonable ? Or maybe not useful at all as Dmitry said (and I agree) On Sun, Nov 10, 2013 at 11:47 AM, Mark S. Miller erig...@google.com wrote: Also function f(args: x, y, z) { will suggest to TypeScript readers that the parameter args has type x. On Sun, Nov 10, 2013 at 11:44 AM, Mark S. Miller erig...@google.comwrote: Hi Brendan and Allen, you are both responding only to my point #1. I consider my point #2 --- cognitive load of the reader on encountering a rarely seen construct --- to be the more significant criticism here. On these grounds, your function f(args: x, y, z) { is worse. Given how : is already used in JS, this suggests that args is either a label name, which the more astute reader can easily disqualify, or a property name, suggesting some shorthand for named parameters. Note that I am not saying that the meanings of all syntactic constructs have to be guessable with no guidance. But the rarely used ones do. 3) Awkward syntax for some rarely used cases is the price of good syntax for common cases. On Sun, Nov 10, 2013 at 11:08 AM, Brendan Eich bren...@mozilla.comwrote: On the other hand, we are this close in ES6 to relieveing people from having to use arguments at all. I like the intention behind Allen's idea. To defend the concrete syntax a bit, one would argue that only the final formal parameter may be prefixed with #, and we are free to use # in other ways elsewhere. If # should be kept reserved even in this context, then perhaps something like function f(args: x, y, z) { // use x, y, z freely (they could be patterns) switch (args.length) { case 1: ... case 2: ... // etc. } } The label names a rest parameter for the entire parameter list. /be Mark S. Miller mailto:erig...@google.com November 10, 2013 6:52 PM 1) # is one of the few ascii characters we haven't used up yet. Let's not use it up on a minor convenience. 2) Introducing new syntax for use cases that are expected to be frequent, e.g., classes, often pays for its weight. The frequency makes it likely that readers will understand what it is the vast majority of times they encounter it. New syntax that gets used once in a blue moon can only be justified if the pain of doing without in those blue-moon cases is huge. In this case, it isn't. For those rare occasions when they see it, readers are much more likely to guess what arguments.length mean that this funny newfangled # thing. Code is read much more often than it is written -- at least code that matters. Brevity is useful as a metric only to the degree that it serves as a proxy for cognitive load on the reader. -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss Allen Wirfs-Brock mailto:al...@wirfs-brock.com November 10, 2013 7:12 PM One of the the few remaining uses of a function's 'arguments' binding is to determine the actual number of passed arguments. This is necessary in some overloading scenarios where a function has different behavior when an argument is completely absent then it has when undefined (or any other default value) is explicitly passed in that parameter position. That situation occurs in a number of DOM APIs and even a few ES library functions. For example(see https://bugs.ecmascript.org/show_bug.cgi?id=1877 ), Array.prototype.splice returns different results for: [1,2,3].splice() and [1,2,3].splice(undefined) The natural ES6 declaration for a splice function is: function splice(start, deleteCount, ...items) {... but if you write it this way then within the body you have to have a test like: if (arguments.length == 0) {... to implement the correct web-compatable behavior. Or, alternatively you could declare the functions as: function splice(...actualArgs) { let [start, stop, ...item] = actualArgs; ... if (actualArgs.length == 0) {... So, to implement a Web-compaable version of splice you either have to use 'arguments' to determine the actual number of passed objects or you need to declare it with a bogus parameter pattern and use explicit or implicit destructuring to parse out the positional parameters. One way around this dilemma would be to provide a syntactic affordance for determing the actual argument count. For example, one possibility would be to allow the last item of any formal parameter list to be an item of the syntactic form: ActualArgumentCount : '#' BindingIdentifier So, the declaration for splice could then be: function splice(start, deleteCount, ...items,
Re: an idea for replacing arguments.length
Good point - between that and your previous message, I withdraw the label idea. /be Sent from my iPhone On Nov 10, 2013, at 7:47 PM, Mark S. Miller erig...@google.com wrote: Also function f(args: x, y, z) { will suggest to TypeScript readers that the parameter args has type x. On Sun, Nov 10, 2013 at 11:44 AM, Mark S. Miller erig...@google.com wrote: Hi Brendan and Allen, you are both responding only to my point #1. I consider my point #2 --- cognitive load of the reader on encountering a rarely seen construct --- to be the more significant criticism here. On these grounds, your function f(args: x, y, z) { is worse. Given how : is already used in JS, this suggests that args is either a label name, which the more astute reader can easily disqualify, or a property name, suggesting some shorthand for named parameters. Note that I am not saying that the meanings of all syntactic constructs have to be guessable with no guidance. But the rarely used ones do. 3) Awkward syntax for some rarely used cases is the price of good syntax for common cases. On Sun, Nov 10, 2013 at 11:08 AM, Brendan Eich bren...@mozilla.com wrote: On the other hand, we are this close in ES6 to relieveing people from having to use arguments at all. I like the intention behind Allen's idea. To defend the concrete syntax a bit, one would argue that only the final formal parameter may be prefixed with #, and we are free to use # in other ways elsewhere. If # should be kept reserved even in this context, then perhaps something like function f(args: x, y, z) { // use x, y, z freely (they could be patterns) switch (args.length) { case 1: ... case 2: ... // etc. } } The label names a rest parameter for the entire parameter list. /be Mark S. Miller mailto:erig...@google.com November 10, 2013 6:52 PM 1) # is one of the few ascii characters we haven't used up yet. Let's not use it up on a minor convenience. 2) Introducing new syntax for use cases that are expected to be frequent, e.g., classes, often pays for its weight. The frequency makes it likely that readers will understand what it is the vast majority of times they encounter it. New syntax that gets used once in a blue moon can only be justified if the pain of doing without in those blue-moon cases is huge. In this case, it isn't. For those rare occasions when they see it, readers are much more likely to guess what arguments.length mean that this funny newfangled # thing. Code is read much more often than it is written -- at least code that matters. Brevity is useful as a metric only to the degree that it serves as a proxy for cognitive load on the reader. -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss Allen Wirfs-Brock mailto:al...@wirfs-brock.com November 10, 2013 7:12 PM One of the the few remaining uses of a function's 'arguments' binding is to determine the actual number of passed arguments. This is necessary in some overloading scenarios where a function has different behavior when an argument is completely absent then it has when undefined (or any other default value) is explicitly passed in that parameter position. That situation occurs in a number of DOM APIs and even a few ES library functions. For example(see https://bugs.ecmascript.org/show_bug.cgi?id=1877 ), Array.prototype.splice returns different results for: [1,2,3].splice() and [1,2,3].splice(undefined) The natural ES6 declaration for a splice function is: function splice(start, deleteCount, ...items) {... but if you write it this way then within the body you have to have a test like: if (arguments.length == 0) {... to implement the correct web-compatable behavior. Or, alternatively you could declare the functions as: function splice(...actualArgs) { let [start, stop, ...item] = actualArgs; ... if (actualArgs.length == 0) {... So, to implement a Web-compaable version of splice you either have to use 'arguments' to determine the actual number of passed objects or you need to declare it with a bogus parameter pattern and use explicit or implicit destructuring to parse out the positional parameters. One way around this dilemma would be to provide a syntactic affordance for determing the actual argument count. For example, one possibility would be to allow the last item of any formal parameter list to be an item of the syntactic form: ActualArgumentCount : '#' BindingIdentifier So, the declaration for splice could then be: function splice(start, deleteCount, ...items, #argCount) { ... if (argCount == 0) {... Thoughts? Allen ___ es-discuss mailing
Re: an idea for replacing arguments.length
The other objection is that counting top level commas misleads. /be On Nov 10, 2013, at 7:21 PM, Allen Wirfs-Brock al...@wirfs-brock.com wrote: The use of : suggests that another alternative could be: function splice(start, deleteCount, ...items, :argCount) { but I still lie # better and don't think this usage would have to impact any other possbile use of that character. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: optional yield expression creates ambiguity
On Nov 10, 2013, at 11:12 AM, Allen Wirfs-Brock wrote: yes sorry, answered without thinking enough. If we want alternative #2 to allow (YieldExpression) even with a required AssignmentExpression then the complexity of doing alternative #2 is about the same as for alternative #3 Allen On Nov 10, 2013, at 11:04 AM, Sam Tobin-Hochstadt wrote: On Sun, Nov 10, 2013 at 1:46 PM, Allen Wirfs-Brock al...@wirfs-brock.com wrote: The actual utility of a YieldExpression in an 'extends' clause seems so low that I don't think we should make the entire expression grammar more complicated just to support alternative #3. It would be possible to just parenthesize the YieldExpression if you actually wanted one in an extends clause, right? Sam ___ 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: an idea for replacing arguments.length
On Nov 10, 2013, at 11:44 AM, Mark S. Miller wrote: Hi Brendan and Allen, you are both responding only to my point #1. I consider my point #2 --- cognitive load of the reader on encountering a rarely seen construct --- to be the more significant criticism here. Hence my choice of using # which is more suggestive to the meaning. It seems suggestive enough that once somebody was initially exposed to it they would understand it when they say it. Note that I am not saying that the meanings of all syntactic constructs have to be guessable with no guidance. But the rarely used ones do. 3) Awkward syntax for some rarely used cases is the price of good syntax for common cases. But sometimes syntax to provide access to basic information or functionality that is rarely used. Arguably 'arguments' already provides such a hook but we are trying to generally discourage use of 'arguments' because of its other undesirable characteristics. A different alternative would be via a new default bind. We could specify that every function has an implicit const bind for 'actualArgCount' (unless there is a different explicit declaration for that name). As for rarity. I've been in enough long discussions with Web API folks on the public-script-coord list and on various WebIDL bugs to feel that this usage to define over-loads isn't that rare in the DOM API world. It would be nice for ES to have a story for handling such definitions other than falling back to using 'arguments' Allen On Sun, Nov 10, 2013 at 11:08 AM, Brendan Eich bren...@mozilla.com wrote: On the other hand, we are this close in ES6 to relieveing people from having to use arguments at all. I like the intention behind Allen's idea. To defend the concrete syntax a bit, one would argue that only the final formal parameter may be prefixed with #, and we are free to use # in other ways elsewhere. If # should be kept reserved even in this context, then perhaps something like function f(args: x, y, z) { // use x, y, z freely (they could be patterns) switch (args.length) { case 1: ... case 2: ... // etc. } } The label names a rest parameter for the entire parameter list. /be Mark S. Miller mailto:erig...@google.com November 10, 2013 6:52 PM 1) # is one of the few ascii characters we haven't used up yet. Let's not use it up on a minor convenience. 2) Introducing new syntax for use cases that are expected to be frequent, e.g., classes, often pays for its weight. The frequency makes it likely that readers will understand what it is the vast majority of times they encounter it. New syntax that gets used once in a blue moon can only be justified if the pain of doing without in those blue-moon cases is huge. In this case, it isn't. For those rare occasions when they see it, readers are much more likely to guess what arguments.length mean that this funny newfangled # thing. Code is read much more often than it is written -- at least code that matters. Brevity is useful as a metric only to the degree that it serves as a proxy for cognitive load on the reader. -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss Allen Wirfs-Brock mailto:al...@wirfs-brock.com November 10, 2013 7:12 PM One of the the few remaining uses of a function's 'arguments' binding is to determine the actual number of passed arguments. This is necessary in some overloading scenarios where a function has different behavior when an argument is completely absent then it has when undefined (or any other default value) is explicitly passed in that parameter position. That situation occurs in a number of DOM APIs and even a few ES library functions. For example(see https://bugs.ecmascript.org/show_bug.cgi?id=1877 ), Array.prototype.splice returns different results for: [1,2,3].splice() and [1,2,3].splice(undefined) The natural ES6 declaration for a splice function is: function splice(start, deleteCount, ...items) {... but if you write it this way then within the body you have to have a test like: if (arguments.length == 0) {... to implement the correct web-compatable behavior. Or, alternatively you could declare the functions as: function splice(...actualArgs) { let [start, stop, ...item] = actualArgs; ... if (actualArgs.length == 0) {... So, to implement a Web-compaable version of splice you either have to use 'arguments' to determine the actual number of passed objects or you need to declare it with a bogus parameter pattern and use explicit or implicit destructuring to parse out the positional parameters. One way around this dilemma would be to provide a syntactic affordance for determing the actual argument count. For example, one possibility
Re: an idea for replacing arguments.length
I don’t fully understand this — what is the reason for needing to know actual argument count? The historical reason was that if i have a var arg function with a few required parameters i don’t have any nice way of iterating the optional args. Default and rest parameters seem to solve this use case. —Oliver On Nov 10, 2013, at 10:12 AM, Allen Wirfs-Brock al...@wirfs-brock.com wrote: One of the the few remaining uses of a function's 'arguments' binding is to determine the actual number of passed arguments. This is necessary in some overloading scenarios where a function has different behavior when an argument is completely absent then it has when undefined (or any other default value) is explicitly passed in that parameter position. That situation occurs in a number of DOM APIs and even a few ES library functions. For example(see https://bugs.ecmascript.org/show_bug.cgi?id=1877 ), Array.prototype.splice returns different results for: [1,2,3].splice() and [1,2,3].splice(undefined) The natural ES6 declaration for a splice function is: function splice(start, deleteCount, ...items) {... but if you write it this way then within the body you have to have a test like: if (arguments.length == 0) {... to implement the correct web-compatable behavior. Or, alternatively you could declare the functions as: function splice(...actualArgs) { let [start, stop, ...item] = actualArgs; ... if (actualArgs.length == 0) {... So, to implement a Web-compaable version of splice you either have to use 'arguments' to determine the actual number of passed objects or you need to declare it with a bogus parameter pattern and use explicit or implicit destructuring to parse out the positional parameters. One way around this dilemma would be to provide a syntactic affordance for determing the actual argument count. For example, one possibility would be to allow the last item of any formal parameter list to be an item of the syntactic form: ActualArgumentCount : '#' BindingIdentifier So, the declaration for splice could then be: function splice(start, deleteCount, ...items, #argCount) { ... if (argCount == 0) {... Thoughts? Allen ___ 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: an idea for replacing arguments.length
Does this become common for those using DOM APIs or for those implementing DOM APIs? If only the latter, well... I want to retire arguments as well. For these rare cases, I would use the patterns involving Combining ... with destructuring patterns in the body ain't too bad. And introducing a new default binding that's implicitly in scope without explicit definition? C'mon Allen. this, arguments, return, and yield already give programmers enough TCP refactoring hazards, such as when converting a for loop to a .forEach. How many red-flag identifiers must programmers scan for before undertaking this refactoring? On Sun, Nov 10, 2013 at 12:42 PM, Allen Wirfs-Brock al...@wirfs-brock.comwrote: On Nov 10, 2013, at 11:44 AM, Mark S. Miller wrote: Hi Brendan and Allen, you are both responding only to my point #1. I consider my point #2 --- cognitive load of the reader on encountering a rarely seen construct --- to be the more significant criticism here. Hence my choice of using # which is more suggestive to the meaning. It seems suggestive enough that once somebody was initially exposed to it they would understand it when they say it. Note that I am not saying that the meanings of all syntactic constructs have to be guessable with no guidance. But the rarely used ones do. 3) Awkward syntax for some rarely used cases is the price of good syntax for common cases. But sometimes syntax to provide access to basic information or functionality that is rarely used. Arguably 'arguments' already provides such a hook but we are trying to generally discourage use of 'arguments' because of its other undesirable characteristics. A different alternative would be via a new default bind. We could specify that every function has an implicit const bind for 'actualArgCount' (unless there is a different explicit declaration for that name). As for rarity. I've been in enough long discussions with Web API folks on the public-script-coord list and on various WebIDL bugs to feel that this usage to define over-loads isn't that rare in the DOM API world. It would be nice for ES to have a story for handling such definitions other than falling back to using 'arguments' Allen On Sun, Nov 10, 2013 at 11:08 AM, Brendan Eich bren...@mozilla.comwrote: On the other hand, we are this close in ES6 to relieveing people from having to use arguments at all. I like the intention behind Allen's idea. To defend the concrete syntax a bit, one would argue that only the final formal parameter may be prefixed with #, and we are free to use # in other ways elsewhere. If # should be kept reserved even in this context, then perhaps something like function f(args: x, y, z) { // use x, y, z freely (they could be patterns) switch (args.length) { case 1: ... case 2: ... // etc. } } The label names a rest parameter for the entire parameter list. /be Mark S. Miller mailto:erig...@google.com November 10, 2013 6:52 PM 1) # is one of the few ascii characters we haven't used up yet. Let's not use it up on a minor convenience. 2) Introducing new syntax for use cases that are expected to be frequent, e.g., classes, often pays for its weight. The frequency makes it likely that readers will understand what it is the vast majority of times they encounter it. New syntax that gets used once in a blue moon can only be justified if the pain of doing without in those blue-moon cases is huge. In this case, it isn't. For those rare occasions when they see it, readers are much more likely to guess what arguments.length mean that this funny newfangled # thing. Code is read much more often than it is written -- at least code that matters. Brevity is useful as a metric only to the degree that it serves as a proxy for cognitive load on the reader. -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss Allen Wirfs-Brock mailto:al...@wirfs-brock.com November 10, 2013 7:12 PM One of the the few remaining uses of a function's 'arguments' binding is to determine the actual number of passed arguments. This is necessary in some overloading scenarios where a function has different behavior when an argument is completely absent then it has when undefined (or any other default value) is explicitly passed in that parameter position. That situation occurs in a number of DOM APIs and even a few ES library functions. For example(see https://bugs.ecmascript.org/show_bug.cgi?id=1877 ), Array.prototype.splice returns different results for: [1,2,3].splice() and [1,2,3].splice(undefined) The natural ES6 declaration for a splice function is: function splice(start, deleteCount, ...items) {... but if you write it this way then within the body you have to have a test like: if (arguments.length == 0) {... to
Re: an idea for replacing arguments.length
Sorry, ignore the line noise I just remembered that we decided to treat undefined as missing. I do recall actually making the argument w.r.t defaults, that treating undefined as “not provided” would cause us difficulty if anyone ever wanted to distinguish undefined from not provided. —Oliver On Nov 10, 2013, at 12:52 PM, Oliver Hunt oli...@apple.com wrote: I don’t fully understand this — what is the reason for needing to know actual argument count? The historical reason was that if i have a var arg function with a few required parameters i don’t have any nice way of iterating the optional args. Default and rest parameters seem to solve this use case. —Oliver On Nov 10, 2013, at 10:12 AM, Allen Wirfs-Brock al...@wirfs-brock.com wrote: One of the the few remaining uses of a function's 'arguments' binding is to determine the actual number of passed arguments. This is necessary in some overloading scenarios where a function has different behavior when an argument is completely absent then it has when undefined (or any other default value) is explicitly passed in that parameter position. That situation occurs in a number of DOM APIs and even a few ES library functions. For example(see https://bugs.ecmascript.org/show_bug.cgi?id=1877 ), Array.prototype.splice returns different results for: [1,2,3].splice() and [1,2,3].splice(undefined) The natural ES6 declaration for a splice function is: function splice(start, deleteCount, ...items) {... but if you write it this way then within the body you have to have a test like: if (arguments.length == 0) {... to implement the correct web-compatable behavior. Or, alternatively you could declare the functions as: function splice(...actualArgs) { let [start, stop, ...item] = actualArgs; ... if (actualArgs.length == 0) {... So, to implement a Web-compaable version of splice you either have to use 'arguments' to determine the actual number of passed objects or you need to declare it with a bogus parameter pattern and use explicit or implicit destructuring to parse out the positional parameters. One way around this dilemma would be to provide a syntactic affordance for determing the actual argument count. For example, one possibility would be to allow the last item of any formal parameter list to be an item of the syntactic form: ActualArgumentCount : '#' BindingIdentifier So, the declaration for splice could then be: function splice(start, deleteCount, ...items, #argCount) { ... if (argCount == 0) {... Thoughts? Allen ___ 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 ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
On Nov 10, 2013, at 12:52 PM, Oliver Hunt wrote: I don’t fully understand this — what is the reason for needing to know actual argument count? The historical reason was that if i have a var arg function with a few required parameters i don’t have any nice way of iterating the optional args. Default and rest parameters seem to solve this use case. The legacy reason is that there are existing APIs that were probably originally implemented in C++ where the behavior of the function was determined by the number of passed arguments rather than by their actual values. The continuing reason is that WebIDL overloading model encourages people to design new APIs that have that same characteristic. And so far, nobody has convinced the WebIDL maintainers to abandon such overloading as a specification technique. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
On Nov 10, 2013, at 12:53 PM, Mark S. Miller wrote: Does this become common for those using DOM APIs or for those implementing DOM APIs? If only the latter, well... I want to retire arguments as well. For these rare cases, I would use the patterns involving Combining ... with destructuring patterns in the body ain't too bad. A problem is that the implementation signature of an API is implemented is what is often document as the as the usage signature. So, if a lot of DOM APIs need to be implemented as function (...args) { then that is likely what will appear in documentation. Also note that there is likely to be actual computational overhead in both creating a rest argument and in destructuring it. In some cases, that overhead may be an issue. And introducing a new default binding that's implicitly in scope without explicit definition? C'mon Allen. this, arguments, return, and yield already give programmers enough TCP refactoring hazards, such as when converting a for loop to a .forEach. How many red-flag identifiers must programmers scan for before undertaking this refactoring? that's why I suggested (...,#argCount) If you don't want to use new syntax then a built-in binding is a fallback solution. Allen On Sun, Nov 10, 2013 at 12:42 PM, Allen Wirfs-Brock al...@wirfs-brock.com wrote: On Nov 10, 2013, at 11:44 AM, Mark S. Miller wrote: Hi Brendan and Allen, you are both responding only to my point #1. I consider my point #2 --- cognitive load of the reader on encountering a rarely seen construct --- to be the more significant criticism here. Hence my choice of using # which is more suggestive to the meaning. It seems suggestive enough that once somebody was initially exposed to it they would understand it when they say it. Note that I am not saying that the meanings of all syntactic constructs have to be guessable with no guidance. But the rarely used ones do. 3) Awkward syntax for some rarely used cases is the price of good syntax for common cases. But sometimes syntax to provide access to basic information or functionality that is rarely used. Arguably 'arguments' already provides such a hook but we are trying to generally discourage use of 'arguments' because of its other undesirable characteristics. A different alternative would be via a new default bind. We could specify that every function has an implicit const bind for 'actualArgCount' (unless there is a different explicit declaration for that name). As for rarity. I've been in enough long discussions with Web API folks on the public-script-coord list and on various WebIDL bugs to feel that this usage to define over-loads isn't that rare in the DOM API world. It would be nice for ES to have a story for handling such definitions other than falling back to using 'arguments' Allen On Sun, Nov 10, 2013 at 11:08 AM, Brendan Eich bren...@mozilla.com wrote: On the other hand, we are this close in ES6 to relieveing people from having to use arguments at all. I like the intention behind Allen's idea. To defend the concrete syntax a bit, one would argue that only the final formal parameter may be prefixed with #, and we are free to use # in other ways elsewhere. If # should be kept reserved even in this context, then perhaps something like function f(args: x, y, z) { // use x, y, z freely (they could be patterns) switch (args.length) { case 1: ... case 2: ... // etc. } } The label names a rest parameter for the entire parameter list. /be Mark S. Miller mailto:erig...@google.com November 10, 2013 6:52 PM 1) # is one of the few ascii characters we haven't used up yet. Let's not use it up on a minor convenience. 2) Introducing new syntax for use cases that are expected to be frequent, e.g., classes, often pays for its weight. The frequency makes it likely that readers will understand what it is the vast majority of times they encounter it. New syntax that gets used once in a blue moon can only be justified if the pain of doing without in those blue-moon cases is huge. In this case, it isn't. For those rare occasions when they see it, readers are much more likely to guess what arguments.length mean that this funny newfangled # thing. Code is read much more often than it is written -- at least code that matters. Brevity is useful as a metric only to the degree that it serves as a proxy for cognitive load on the reader. -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss Allen Wirfs-Brock mailto:al...@wirfs-brock.com November 10, 2013 7:12 PM One of the the few remaining uses of a function's 'arguments' binding is to determine the actual number of passed arguments. This is necessary in some
Re: an idea for replacing arguments.length
fwiw, I have few APIs that use null or undefined / void 0 as explicit action to remove an item ... an example. ```javascript function cookie(key, value) { if (arguments.length === 1) return get(key); if (value == null) return del(key); set(key, value); return value; } ``` Although I would use `function cookie(...args){}` as soon as supported and/or `arguments` would be undefined ... no big deal. In the other case I would simply do something like: ``` function splice(a, b, ...rest) { var numArgs = rest.length + (b !== void 0) + (a !== void 0); } ``` Not sure why this is so needed though. Cheers On Sun, Nov 10, 2013 at 12:59 PM, Allen Wirfs-Brock al...@wirfs-brock.comwrote: On Nov 10, 2013, at 12:52 PM, Oliver Hunt wrote: I don’t fully understand this — what is the reason for needing to know actual argument count? The historical reason was that if i have a var arg function with a few required parameters i don’t have any nice way of iterating the optional args. Default and rest parameters seem to solve this use case. The legacy reason is that there are existing APIs that were probably originally implemented in C++ where the behavior of the function was determined by the number of passed arguments rather than by their actual values. The continuing reason is that WebIDL overloading model encourages people to design new APIs that have that same characteristic. And so far, nobody has convinced the WebIDL maintainers to abandon such overloading as a specification technique. Allen ___ 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: an idea for replacing arguments.length
On Nov 10, 2013, at 9:12 PM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: Not sure why this is so needed though. Allen's posts make the case: webidl and varargs-style functions. Not all legacy. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
Le 10/11/2013 22:19, Brendan Eich a écrit : On Nov 10, 2013, at 9:12 PM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: Not sure why this is so needed though. Allen's posts make the case: webidl and varargs-style functions. Not all legacy. WebIDL creates spec, not code. The language syntax doesn't need to evolve for that. Allen showed that rest params+destructuring allows self-hosting without |arguments| Varargs functions have rest parameters. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
The mere fact the this discussion is coming up, is a good argument (to me anyway) that default parameter behaviour should have been in terms of argument count, not |undefined|. Again, sentinel values that are regular valid values are a bad thing. I still cannot recall what the usage scenario that required undefined = not provided was, but this seems like a very good argument for that decision being wrong. —Oliver On Nov 10, 2013, at 1:19 PM, Brendan Eich bren...@mozilla.com wrote: On Nov 10, 2013, at 9:12 PM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: Not sure why this is so needed though. Allen's posts make the case: webidl and varargs-style functions. Not all legacy. /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: an idea for replacing arguments.length
On Sun, Nov 10, 2013 at 1:08 PM, Allen Wirfs-Brock al...@wirfs-brock.comwrote: On Nov 10, 2013, at 12:53 PM, Mark S. Miller wrote: Does this become common for those using DOM APIs or for those implementing DOM APIs? If only the latter, well... I want to retire arguments as well. For these rare cases, I would use the patterns involving Combining ... with destructuring patterns in the body ain't too bad. A problem is that the implementation signature of an API is implemented is what is often document as the as the usage signature. So, if a lot of DOM APIs need to be implemented as function (...args) { then that is likely what will appear in documentation. Generate the documentation from the WebIDL. Also note that there is likely to be actual computational overhead in both creating a rest argument and in destructuring it. In some cases, that overhead may be an issue. When it is a performance cost, use arguments.length. I hate it, but less than adding a new feature to the language merely to make an anti-pattern more convenient. And introducing a new default binding that's implicitly in scope without explicit definition? C'mon Allen. this, arguments, return, and yield already give programmers enough TCP refactoring hazards, such as when converting a for loop to a .forEach. How many red-flag identifiers must programmers scan for before undertaking this refactoring? that's why I suggested (...,#argCount) If you don't want to use new syntax then a built-in binding is a fallback solution. I agree that #argCount is better than introducing a new builtin binding. #argCount is also better than being hit on the head with a hammer. Allen On Sun, Nov 10, 2013 at 12:42 PM, Allen Wirfs-Brock al...@wirfs-brock.com wrote: On Nov 10, 2013, at 11:44 AM, Mark S. Miller wrote: Hi Brendan and Allen, you are both responding only to my point #1. I consider my point #2 --- cognitive load of the reader on encountering a rarely seen construct --- to be the more significant criticism here. Hence my choice of using # which is more suggestive to the meaning. It seems suggestive enough that once somebody was initially exposed to it they would understand it when they say it. Note that I am not saying that the meanings of all syntactic constructs have to be guessable with no guidance. But the rarely used ones do. 3) Awkward syntax for some rarely used cases is the price of good syntax for common cases. But sometimes syntax to provide access to basic information or functionality that is rarely used. Arguably 'arguments' already provides such a hook but we are trying to generally discourage use of 'arguments' because of its other undesirable characteristics. A different alternative would be via a new default bind. We could specify that every function has an implicit const bind for 'actualArgCount' (unless there is a different explicit declaration for that name). As for rarity. I've been in enough long discussions with Web API folks on the public-script-coord list and on various WebIDL bugs to feel that this usage to define over-loads isn't that rare in the DOM API world. It would be nice for ES to have a story for handling such definitions other than falling back to using 'arguments' Allen On Sun, Nov 10, 2013 at 11:08 AM, Brendan Eich bren...@mozilla.comwrote: On the other hand, we are this close in ES6 to relieveing people from having to use arguments at all. I like the intention behind Allen's idea. To defend the concrete syntax a bit, one would argue that only the final formal parameter may be prefixed with #, and we are free to use # in other ways elsewhere. If # should be kept reserved even in this context, then perhaps something like function f(args: x, y, z) { // use x, y, z freely (they could be patterns) switch (args.length) { case 1: ... case 2: ... // etc. } } The label names a rest parameter for the entire parameter list. /be Mark S. Miller mailto:erig...@google.com November 10, 2013 6:52 PM 1) # is one of the few ascii characters we haven't used up yet. Let's not use it up on a minor convenience. 2) Introducing new syntax for use cases that are expected to be frequent, e.g., classes, often pays for its weight. The frequency makes it likely that readers will understand what it is the vast majority of times they encounter it. New syntax that gets used once in a blue moon can only be justified if the pain of doing without in those blue-moon cases is huge. In this case, it isn't. For those rare occasions when they see it, readers are much more likely to guess what arguments.length mean that this funny newfangled # thing. Code is read much more often than it is written -- at least code that matters. Brevity is useful as a metric only to the degree that it serves as a proxy for cognitive load on the reader. -- Cheers, --MarkM
Re: an idea for replacing arguments.length
Le 10/11/2013 22:30, K. Gadd a écrit : JSIL and embind both need arguments.length for efficient method call dispatch when dealing with overloaded functions. Is it your intent that all such scenarios must now pay the cost of creating an array (to hold the rest arguments) and then destructuring it, for every call? At present it's possible to avoid this overhead in V8 and SpiderMonkey by using arguments.length + arguments[n] or by using arguments.length + patterned argument names. The array created by rest arguments has no reason to cost more than the arguments object. It's only an implementation concern. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
On Nov 10, 2013, at 9:24 PM, David Bruant bruan...@gmail.com wrote: WebIDL creates spec, not code. The language syntax doesn't need to evolve for that. Wrong, webidl and jsidl (and jsil and embind) are both interface and a bit of implementation. Testing argc != testing sentinel value. Two different semantics, plausibly deserving fast and terse syntax. Allen showed that rest params+destructuring allows self Read Allen's replies, stop ignoring known counter-arguments. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
On Sun, Nov 10, 2013 at 1:30 PM, K. Gadd k...@luminance.org wrote: JSIL and embind both need arguments.length for efficient method call dispatch when dealing with overloaded functions. Is it your intent that all such scenarios must now pay the cost of creating an array (to hold the rest arguments) and then destructuring it, for every call? At present it's possible to avoid this overhead in V8 and SpiderMonkey by using arguments.length + arguments[n] or by using arguments.length + patterned argument names. Hi Katelyn, No one is taking arguments away. Perhaps we would if we could but we can't. So as I said just now to Allen, if you really need to do this, go ahead and use arguments.length. But do you really need to do this? Assuming for a moment that we were all agreed that the best practice is to treat absence the same as undefined, why not go with the best practice and be done? On Sun, Nov 10, 2013 at 1:24 PM, David Bruant bruan...@gmail.com wrote: Le 10/11/2013 22:19, Brendan Eich a écrit : On Nov 10, 2013, at 9:12 PM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: Not sure why this is so needed though. Allen's posts make the case: webidl and varargs-style functions. Not all legacy. WebIDL creates spec, not code. The language syntax doesn't need to evolve for that. Allen showed that rest params+destructuring allows self-hosting without |arguments| Varargs functions have rest parameters. 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 -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
On Nov 10, 2013, at 9:32 PM, Oliver Hunt oli...@apple.com wrote: I still cannot recall what the usage scenario that required undefined = not provided was, but this seems like a very good argument for that decision being wrong. C'mon, we have been over this a kajillion times. Delegation without sentinels requires explosive case analysis and call sites in the delegating functions. Don't let the varargs but not sentinel fixable case be the tail that wags the dog. Here, we are debating fine hairs on the tail. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
On Nov 10, 2013, at 1:08 PM, Allen Wirfs-Brock wrote: On Nov 10, 2013, at 12:53 PM, Mark S. Miller wrote: Does this become common for those using DOM APIs or for those implementing DOM APIs? If only the latter, well... I want to retire arguments as well. For these rare cases, I would use the patterns involving Combining ... with destructuring patterns in the body ain't too bad. A problem is that the implementation signature of an API is implemented is what is often document as the as the usage signature. So, if a lot of DOM APIs need to be implemented as function (...args) { then that is likely what will appear in documentation. Also note that there is likely to be actual computational overhead in both creating a rest argument and in destructuring it. In some cases, that overhead may be an issue. I think I'm with Mark here, and as mentioned, don't think spreading two equivalent ways of doing the same thing (`args.length` and #count in case when have only the `...args`) is the best design decision. Yes, it's true that destructuring could make some overhead, but no one is tight to use it: a var-args function still can be described as `...args` only and check its length as it does with the `arguments`. Moreover, for this particular `splice` example, I don't think the `(start, deleteCount, ...rest)` is the best signature (not to say, incorrect signature). As again was mentioned, a var-args function seems should just use the `...rest` params, and exactly starting from the position when the first optional argument is started. And if it's started right from the position 0 (as with the `splice`), then probably the more natural signature would be the `(...args)`. P.S.: I do also agree that it's better to reserve the syntax of `(foo: bar)` for the optional types (that are used in TypeScript now). Dmitry ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
Le 10/11/2013 22:42, Brendan Eich a écrit : On Nov 10, 2013, at 9:24 PM, David Bruant bruan...@gmail.com wrote: WebIDL creates spec, not code. The language syntax doesn't need to evolve for that. Wrong, webidl and jsidl (and jsil and embind) are both interface and a bit of implementation. Testing argc != testing sentinel value. Two different semantics, plausibly deserving fast and terse syntax. One of the semantics is admitted as a bad practice. I still don't understand why it should be encouraged. Other use cases are compile-to-JS use case. Can implementations optimize the pattern Allen showed in his initial post? function splice(...actualArgs) { let [start, stop, ...item] = actualArgs; ... if (actualArgs.length == 0) {... Allen showed that rest params+destructuring allows self Read Allen's replies, stop ignoring known counter-arguments. Not my intention, sorry it came out this way, I had missed a few posts. Allen wrote: So, if a lot of DOM APIs need to be implemented as function (...args) { then that is likely what will appear in documentation. As Mark said, generate doc from WebIDL. Else, MDN and WPD are CC-licenced wikis :-) Also note that there is likely to be actual computational overhead in both creating a rest argument and in destructuring it. In some cases, that overhead may be an issue. Can implementations optimize this pattern to remove this overhead? David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
I think I've completely missed the `undefined === absent` conversation ... so if I have an object, and `obj.key = void 0` why `key` would be considered absent, exactly? `undefined` is a very well described value, passing stuff around thinking has a value but getting ignored by signatures and who knows what else is a door to hell in the real world. my 2 cents On Sun, Nov 10, 2013 at 1:49 PM, Mark S. Miller erig...@google.com wrote: On Sun, Nov 10, 2013 at 1:30 PM, K. Gadd k...@luminance.org wrote: JSIL and embind both need arguments.length for efficient method call dispatch when dealing with overloaded functions. Is it your intent that all such scenarios must now pay the cost of creating an array (to hold the rest arguments) and then destructuring it, for every call? At present it's possible to avoid this overhead in V8 and SpiderMonkey by using arguments.length + arguments[n] or by using arguments.length + patterned argument names. Hi Katelyn, No one is taking arguments away. Perhaps we would if we could but we can't. So as I said just now to Allen, if you really need to do this, go ahead and use arguments.length. But do you really need to do this? Assuming for a moment that we were all agreed that the best practice is to treat absence the same as undefined, why not go with the best practice and be done? On Sun, Nov 10, 2013 at 1:24 PM, David Bruant bruan...@gmail.com wrote: Le 10/11/2013 22:19, Brendan Eich a écrit : On Nov 10, 2013, at 9:12 PM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: Not sure why this is so needed though. Allen's posts make the case: webidl and varargs-style functions. Not all legacy. WebIDL creates spec, not code. The language syntax doesn't need to evolve for that. Allen showed that rest params+destructuring allows self-hosting without |arguments| Varargs functions have rest parameters. 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 -- Cheers, --MarkM ___ 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: an idea for replacing arguments.length
Dispatching entirely off argument types and not anything else (like count) is an interesting idea. I'm not sure it's on topic for this discussion though. Is there a way to actually do type dispatch in ES at present, let alone efficiently? Based on my understanding of current VMs, you'd have to do a song and dance (per argument) like this: Is it undefined? Terminate argument scanning. Check typeof to see if it is a special type; dispatch based on that if so. If it's not a special type, check to see if it's null. If so, dispatch based on 'object' since you can't know more about the type than that and have to guess. If it's not null, call Object.getPrototypeOf and then somehow look up that prototype against the type information you're doing overload dispatch against. It's not clear to me how this would interact with newish features like proxies, either, but I suppose it would at least work. At present doing fast dispatch based on argument count and THEN only doing per-argument type checks if necessary is a huge performance boost because VMs can actually generate relatively fast native code for an arguments.length check. Typeof checks and getPrototypeOf do not generally produce fast code in my experience so it would be problematic to do them for every overloaded call site instead of just call sites that actually care about the types of particular arguments. Doing this type of dispatch is comparatively simple in .NET since for any non-null value you can request a Type object for it (via GetType) and then use that as a key into a lookup table/dictionary - so the operation becomes 'if (x == null) typeId = 0 else typeId = typeTable[x.getType()]' or something along those lines, which you can optimize down to a set of conditionals when the number of types you care about is small. The fact that ES does not allow setting properties on all values means it's impossible to hang type information off values like that. To put it another way, if I have an overloaded functions with two signatures - like say writeline(s) and writeline(f, s) - then in practice I just dispatch off the argument count. Because there are not multiple signatures with the same count, there's no way the user could have intended to call something else. In use cases where correctness is more important, you'd probably want to rigorously check every argument and dispatch off that. From a performance perspective I also find the idea of having to 'scan' the arguments list sequentially looking for an undefined sentinel to be pretty gross. Do we really need to introduce the awful null terminated string pattern, along with all its problems, in more places? On Sun, Nov 10, 2013 at 1:49 PM, Mark S. Miller erig...@google.com wrote: On Sun, Nov 10, 2013 at 1:30 PM, K. Gadd k...@luminance.org wrote: JSIL and embind both need arguments.length for efficient method call dispatch when dealing with overloaded functions. Is it your intent that all such scenarios must now pay the cost of creating an array (to hold the rest arguments) and then destructuring it, for every call? At present it's possible to avoid this overhead in V8 and SpiderMonkey by using arguments.length + arguments[n] or by using arguments.length + patterned argument names. Hi Katelyn, No one is taking arguments away. Perhaps we would if we could but we can't. So as I said just now to Allen, if you really need to do this, go ahead and use arguments.length. But do you really need to do this? Assuming for a moment that we were all agreed that the best practice is to treat absence the same as undefined, why not go with the best practice and be done? On Sun, Nov 10, 2013 at 1:24 PM, David Bruant bruan...@gmail.com wrote: Le 10/11/2013 22:19, Brendan Eich a écrit : On Nov 10, 2013, at 9:12 PM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: Not sure why this is so needed though. Allen's posts make the case: webidl and varargs-style functions. Not all legacy. WebIDL creates spec, not code. The language syntax doesn't need to evolve for that. Allen showed that rest params+destructuring allows self-hosting without |arguments| Varargs functions have rest parameters. 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 -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
On Nov 10, 2013, at 2:12 PM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: I think I've completely missed the `undefined === absent` conversation ... so if I have an object, and `obj.key = void 0` why `key` would be considered absent, exactly? `undefined` is a very well described value, passing stuff around thinking has a value but getting ignored by signatures and who knows what else is a door to hell in the real world. void expression simply evaluates expression and sets the return continuation value to undefined. void 0 is identical to |undefined| unless a containing scope has declared a variable named “undefined” locally. void … does not result in a special value. —Oliver my 2 cents On Sun, Nov 10, 2013 at 1:49 PM, Mark S. Miller erig...@google.com wrote: On Sun, Nov 10, 2013 at 1:30 PM, K. Gadd k...@luminance.org wrote: JSIL and embind both need arguments.length for efficient method call dispatch when dealing with overloaded functions. Is it your intent that all such scenarios must now pay the cost of creating an array (to hold the rest arguments) and then destructuring it, for every call? At present it's possible to avoid this overhead in V8 and SpiderMonkey by using arguments.length + arguments[n] or by using arguments.length + patterned argument names. Hi Katelyn, No one is taking arguments away. Perhaps we would if we could but we can't. So as I said just now to Allen, if you really need to do this, go ahead and use arguments.length. But do you really need to do this? Assuming for a moment that we were all agreed that the best practice is to treat absence the same as undefined, why not go with the best practice and be done? On Sun, Nov 10, 2013 at 1:24 PM, David Bruant bruan...@gmail.com wrote: Le 10/11/2013 22:19, Brendan Eich a écrit : On Nov 10, 2013, at 9:12 PM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: Not sure why this is so needed though. Allen's posts make the case: webidl and varargs-style functions. Not all legacy. WebIDL creates spec, not code. The language syntax doesn't need to evolve for that. Allen showed that rest params+destructuring allows self-hosting without |arguments| Varargs functions have rest parameters. 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 -- Cheers, --MarkM ___ 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 ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
Dmitry Soshnikov wrote: Moreover, for this particular `splice` example, I don't think the `(start, deleteCount, ...rest)` is the best signature (not to say, incorrect signature). As again was mentioned, a var-args function seems should just use the `...rest` params, and exactly starting from the position when the first optional argument is started. And if it's started right from the position 0 (as with the `splice`), then probably the more natural signature would be the `(...args)`. This gives the wrong function.length result, though (as Allen pointed out). P.S.: I do also agree that it's better to reserve the syntax of `(foo: bar)` for the optional types (that are used in TypeScript now). Indeed! /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
David Bruant wrote: Also note that there is likely to be actual computational overhead in both creating a rest argument and in destructuring it. In some cases, that overhead may be an issue. Can implementations optimize this pattern to remove this overhead? Surely they can. Will they? If it matters. I'm with you and Mark by default, we have rest, we have defaults, we don't need much more. But the residual arguments.length use-case is vexing. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
Le 10/11/2013 23:34, Brendan Eich a écrit : Dmitry Soshnikov wrote: Moreover, for this particular `splice` example, I don't think the `(start, deleteCount, ...rest)` is the best signature (not to say, incorrect signature). As again was mentioned, a var-args function seems should just use the `...rest` params, and exactly starting from the position when the first optional argument is started. And if it's started right from the position 0 (as with the `splice`), then probably the more natural signature would be the `(...args)`. This gives the wrong function.length result, though (as Allen pointed out). I wrote in an earlier message that function length is writable, but I was confusing with function name... Sorry about that. Would it make sense to make function length writable? David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
I hate arguments.length as well. But given that we can't get rid of it, the occasional idiomatic use is not *that* vexing. In strict mode arguments is effectively a reserved word. If the only use of arguments within a strict function is arguments.length, this will be visible both to humans and to tools. Implementations can trivially implement this by without reifying the arguments object, if it matters. switch (arguments.count) { simply becomes an idiom that two sorts of people learn: 1) Those who wish to engage in this anti-pattern. 2) Those who wish to understand code using the anti-pattern (and possibly berate their authors). On Sun, Nov 10, 2013 at 2:35 PM, Brendan Eich bren...@mozilla.com wrote: David Bruant wrote: Also note that there is likely to be actual computational overhead in both creating a rest argument and in destructuring it. In some cases, that overhead may be an issue. Can implementations optimize this pattern to remove this overhead? Surely they can. Will they? If it matters. I'm with you and Mark by default, we have rest, we have defaults, we don't need much more. But the residual arguments.length use-case is vexing. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- Text by me above is hereby placed in the public domain Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
void 0 is identical to undefined, I perfectly know it, and I have no idea who decided that undefined === absent .. ``` alert(absent); // this is error alert(undefined); // this is undefined var undefined; ``` I think ignoring undefined, if that's what has been decided, is a mistake. As easy as that. On Sun, Nov 10, 2013 at 2:20 PM, Oliver Hunt oli...@apple.com wrote: On Nov 10, 2013, at 2:12 PM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: I think I've completely missed the `undefined === absent` conversation ... so if I have an object, and `obj.key = void 0` why `key` would be considered absent, exactly? `undefined` is a very well described value, passing stuff around thinking has a value but getting ignored by signatures and who knows what else is a door to hell in the real world. void expression simply evaluates expression and sets the return continuation value to undefined. void 0 is identical to |undefined| unless a containing scope has declared a variable named “undefined” locally. void … does not result in a special value. —Oliver my 2 cents On Sun, Nov 10, 2013 at 1:49 PM, Mark S. Miller erig...@google.comwrote: On Sun, Nov 10, 2013 at 1:30 PM, K. Gadd k...@luminance.org wrote: JSIL and embind both need arguments.length for efficient method call dispatch when dealing with overloaded functions. Is it your intent that all such scenarios must now pay the cost of creating an array (to hold the rest arguments) and then destructuring it, for every call? At present it's possible to avoid this overhead in V8 and SpiderMonkey by using arguments.length + arguments[n] or by using arguments.length + patterned argument names. Hi Katelyn, No one is taking arguments away. Perhaps we would if we could but we can't. So as I said just now to Allen, if you really need to do this, go ahead and use arguments.length. But do you really need to do this? Assuming for a moment that we were all agreed that the best practice is to treat absence the same as undefined, why not go with the best practice and be done? On Sun, Nov 10, 2013 at 1:24 PM, David Bruant bruan...@gmail.comwrote: Le 10/11/2013 22:19, Brendan Eich a écrit : On Nov 10, 2013, at 9:12 PM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: Not sure why this is so needed though. Allen's posts make the case: webidl and varargs-style functions. Not all legacy. WebIDL creates spec, not code. The language syntax doesn't need to evolve for that. Allen showed that rest params+destructuring allows self-hosting without |arguments| Varargs functions have rest parameters. 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 -- Cheers, --MarkM ___ 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 ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
Andrea Giammarchi wrote: I think ignoring undefined, if that's what has been decided, is a mistake. As easy as that. Read this thread, or past threads: https://mail.mozilla.org/pipermail/es-discuss/2013-September/033406.html which links to https://mail.mozilla.org/pipermail/es-discuss/2012-June/023402.html where I called for agreement, and https://mail.mozilla.org/pipermail/es-discuss/2012-July/024207.html where (find B. Defaults) the agreement is recorded, with use-case-based rationale. I sometimes think people don't want to remember what they don't agree with. I find that I do that sometimes -- human nature, not sure if it has a cog-psych name. Anyway, it's better to remember, or try to re-deduce the rationale, and argue with that. Not just fail to see why and assert to the contrary. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
On Sun, Nov 10, 2013 at 2:53 PM, Brendan Eich bren...@mozilla.com wrote: Andrea Giammarchi wrote: I think ignoring undefined, if that's what has been decided, is a mistake. As easy as that. Read this thread, or past threads: https://mail.mozilla.org/pipermail/es-discuss/2013-September/033406.html which links to https://mail.mozilla.org/pipermail/es-discuss/2012-June/023402.html where I called for agreement, and https://mail.mozilla.org/pipermail/es-discuss/2012-July/024207.html where (find B. Defaults) the agreement is recorded, with use-case-based rationale. I sometimes think people don't want to remember what they don't agree with. I find that I do that sometimes -- human nature, not sure if it has a cog-psych name. http://en.wikipedia.org/wiki/Confirmation_bias *Confirmation bias* (also called *confirmatory bias* or *myside bias*) is a tendency of people to favor information that confirms their beliefs or hypotheses http://en.wikipedia.org/wiki/Hypothesis.[Note 1]http://en.wikipedia.org/wiki/Confirmation_bias#cite_note-1 [1] http://en.wikipedia.org/wiki/Confirmation_bias#cite_note-plous233-2 People display this bias when they gather or remember information selectively, or when they interpret it in a biased wayhttp://en.wikipedia.org/wiki/Cognitive_bias . Anyway, it's better to remember, or try to re-deduce the rationale, and argue with that. Not just fail to see why and assert to the contrary. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- Text by me above is hereby placed in the public domain Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
Mark Miller wrote: http://en.wikipedia.org/wiki/Confirmation_bias *Confirmation bias* (also called *confirmatory bias* or *myside bias*) is a tendency of people to favor information that confirms their beliefs or hypotheses http://en.wikipedia.org/wiki/Hypothesis.^[Note 1] http://en.wikipedia.org/wiki/Confirmation_bias#cite_note-1 ^[1] http://en.wikipedia.org/wiki/Confirmation_bias#cite_note-plous233-2 People display this bias when they gather or remember information selectively, or when they interpret it in a biased way http://en.wikipedia.org/wiki/Cognitive_bias. Quite broad, was hoping for something narrower, with a catchier name ;-). /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
David Bruant wrote: Le 10/11/2013 23:34, Brendan Eich a écrit : Dmitry Soshnikov wrote: Moreover, for this particular `splice` example, I don't think the `(start, deleteCount, ...rest)` is the best signature (not to say, incorrect signature). As again was mentioned, a var-args function seems should just use the `...rest` params, and exactly starting from the position when the first optional argument is started. And if it's started right from the position 0 (as with the `splice`), then probably the more natural signature would be the `(...args)`. This gives the wrong function.length result, though (as Allen pointed out). I wrote in an earlier message that function length is writable, but I was confusing with function name... Sorry about that. Would it make sense to make function length writable? It is configurable non-writable in ES6, by design. Still a pain to farble from its useless default in this case (via Object.defineProperty). /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
You replied as if I took part in those conversations and forgot ... that might be the case but AFAIK (indeed) is not. However, I am not saying that explicit undefined should not result in the default argument value, when specified, I am saying that passing explicitly undefined should not be ignored. Reading that looks like the agreement is that explicit or not, if an argument has a default, it should be used when undefined is the (un)received value and I agree on that. Here we are saying that undefined would result in a non argument so that whatever(undefined) would have an `arguments.length === 0` unless I've misunderstood this part of the thread (which might be as well) I won't re-quote the part in any case and if I misunderstood then all good and thanks. Cheers On Sun, Nov 10, 2013 at 2:53 PM, Brendan Eich bren...@mozilla.com wrote: Andrea Giammarchi wrote: I think ignoring undefined, if that's what has been decided, is a mistake. As easy as that. Read this thread, or past threads: https://mail.mozilla.org/pipermail/es-discuss/2013-September/033406.html which links to https://mail.mozilla.org/pipermail/es-discuss/2012-June/023402.html where I called for agreement, and https://mail.mozilla.org/pipermail/es-discuss/2012-July/024207.html where (find B. Defaults) the agreement is recorded, with use-case-based rationale. I sometimes think people don't want to remember what they don't agree with. I find that I do that sometimes -- human nature, not sure if it has a cog-psych name. Anyway, it's better to remember, or try to re-deduce the rationale, and argue with that. Not just fail to see why and assert to the contrary. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
From: Allen Wirfs-Brock al...@wirfs-brock.com One of the the few remaining uses of a function's 'arguments' binding is to determine the actual number of passed arguments. This is necessary in some overloading scenarios where a function has different behavior when an argument is completely absent then it has when undefined (or any other default value) is explicitly passed in that parameter position. I'd just like to say that I wouldn't rule out a creative solution that'd allow better function overloading. The problem is not the fact the arguments number isn't reachable without the context decided arguments imho. The problem is that overloading is something that is very useful to do, and we'd like to be able different functions based on the number of parameters. While optional parameters, and rest parameters are really useful and solve a lot of the use cases we'd need overloading for - it's clear that there are use cases it does not address. I'm not sure that tackling the problem by adding new syntax for the number of params is the best approach (although I'd hate to have to resort to arguments, explicitly or implicitly like in the example given). ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
On Nov 10, 2013, at 3:31 PM, Benjamin (Inglor) Gruenbaum wrote: From: Allen Wirfs-Brock al...@wirfs-brock.com One of the the few remaining uses of a function's 'arguments' binding is to determine the actual number of passed arguments. This is necessary in some overloading scenarios where a function has different behavior when an argument is completely absent then it has when undefined (or any other default value) is explicitly passed in that parameter position. I'd just like to say that I wouldn't rule out a creative solution that'd allow better function overloading. The problem is not the fact the arguments number isn't reachable without the context decided arguments imho. The problem is that overloading is something that is very useful to do, and we'd like to be able different functions based on the number of parameters. While optional parameters, and rest parameters are really useful and solve a lot of the use cases we'd need overloading for - it's clear that there are use cases it does not address. I'm not sure that tackling the problem by adding new syntax for the number of params is the best approach (although I'd hate to have to resort to arguments, explicitly or implicitly like in the example given). Declarative overloading in a dynamically typed language is tricky and programmers with static language experience too often try to pretend that they can do JS overloading just like they would do it in C++ or Java. I think the only sort of declarative overloading that is appropriate for JS is based upon the number of actually passed arguments (and nothing else). If you agree with that, then there is a pretty straightforward pattern for expressing that in ES6: function f(...args) { //an overloaded frunction switch (args.length) { case 0: { /* body of the no arguments overload */ } case 1: { let single parameter pattern ] = args; /* body of the 1 argument overload */ } case 2: { let [ two parameter pattern ] = args; /* body of the 2 argument overload */ } case 3: { let [ three parameter pattern ] = args; /* body of the 3 argument overload */ } ... default: { let [ n + rest parameter pattern ] = args; /* body of the n+rest argument overload */ } } } This is a pattern that would be pretty easy for engines to recognize, avoid creating an actual 'args' object, and map the selected cases destructed parameters directly onto the passed argument on the stack. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
Couldn’t this be handled by pattern matching? Two steps would be necessary to do so (I know that the second one is controversial, but hear me out). First: introduce a pattern matching construct. ```js function splice(...args) { match(args) { case [start, stop, ...item]: ... case []: ... } ... } ``` Second: Matching an array fails if the right-hand side does not have the correct length. Two arguments in favor of this approach: – If you want things to be more lenient, you can always use the rest operator. – To me (subjectively), it feels cognitively right. Matching against [x, y] seems fundamentally different from matching against { 0: x, 1: y }. In the former case, length and order of elements matters, in the latter case, it doesn’t. The neat things is that #2 would also enable the enforcement of an arity: function foo(args) { let [must, have, four, params] = args; // exception if arity != 4 } On 11 Nov 2013, at 2:12 , Allen Wirfs-Brock al...@wirfs-brock.com wrote: One of the the few remaining uses of a function's 'arguments' binding is to determine the actual number of passed arguments. This is necessary in some overloading scenarios where a function has different behavior when an argument is completely absent then it has when undefined (or any other default value) is explicitly passed in that parameter position. That situation occurs in a number of DOM APIs and even a few ES library functions. For example(see https://bugs.ecmascript.org/show_bug.cgi?id=1877 ), Array.prototype.splice returns different results for: [1,2,3].splice() and [1,2,3].splice(undefined) The natural ES6 declaration for a splice function is: function splice(start, deleteCount, ...items) {... but if you write it this way then within the body you have to have a test like: if (arguments.length == 0) {... to implement the correct web-compatable behavior. Or, alternatively you could declare the functions as: function splice(...actualArgs) { let [start, stop, ...item] = actualArgs; ... if (actualArgs.length == 0) {... So, to implement a Web-compaable version of splice you either have to use 'arguments' to determine the actual number of passed objects or you need to declare it with a bogus parameter pattern and use explicit or implicit destructuring to parse out the positional parameters. One way around this dilemma would be to provide a syntactic affordance for determing the actual argument count. For example, one possibility would be to allow the last item of any formal parameter list to be an item of the syntactic form: ActualArgumentCount : '#' BindingIdentifier So, the declaration for splice could then be: function splice(start, deleteCount, ...items, #argCount) { ... if (argCount == 0) {... Thoughts? Allen -- Dr. Axel Rauschmayer a...@rauschma.de home: rauschma.de twitter: twitter.com/rauschma blog: 2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
Andrea Giammarchi wrote: You replied as if I took part in those conversations and forgot ... that might be the case but AFAIK (indeed) is not. You are on the list, this came up less than two months ago. Google site search works, please use it. site:mail.mozilla.org es-discuss undefined defaulting is one way, there are others. However, I am not saying that explicit undefined should not result in the default argument value, when specified, I am saying that passing explicitly undefined should not be ignored. Reading that looks like the agreement is that explicit or not, if an argument has a default, it should be used when undefined is the (un)received value and I agree on that. Here we are saying that undefined would result in a non argument so that whatever(undefined) would have an `arguments.length === 0` unless I've misunderstood this part of the thread (which might be as well) No, arguments.length would be 1 per ES6 -- that's important for both delegation and varargs-style (arguments.length-based) dispatching. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
Allen Wirfs-Brock wrote: Can someone remind me what we decided about 'arguments' and arrow functions. I pretty sure we discussed this recently and reach some conclusion but I can't find it in either meeting notes or es-discuss. And I don't trust the correctness of what the spec. draft currently says about this. Any pointers? The /Identifier/ primary expression |arguments| may not be used in an arrow function’s body (whether expression or block form). Likewise, |yield| may not be used in an arrow function’s body. Arrows cannot be generators and we do not want deep continuations. from http://wiki.ecmascript.org/doku.php?id=harmony:arrow_function_syntax. Meeting notes back this. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
RE: an idea for replacing arguments.length
As of 6 months ago there was a shift toward treating it the same as `super`, i.e. use the enclosing scope's. I feel like this was agreed on more recently too. But I am not sure. http://esdiscuss.org/topic/introduction-comprehensions-beyond-arrays#content-1 ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
Domenic Denicola wrote: As of 6 months ago there was a shift toward treating it the same as `super`, i.e. use the enclosing scope's. I feel like this was agreed on more recently too. But I am not sure. http://esdiscuss.org/topic/introduction-comprehensions-beyond-arrays#content-1 From http://esdiscuss.org/topic/introduction-comprehensions-beyond-arrays#content-23 and adjacent (the one after is the last I see), we did not reach agreement, and seemed to go back to arguments in an arrow body expression or block being an error. We should discuss at this month's TC39 meeting in 2 weeks. Adding it to the agenda. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: optional yield expression creates ambiguity
Python has requirements for over-parenthesization which we were trying to avoid. Nevertheless, did you consider 5. Except on right of assignment and in actual argument position, yield expressions must be parenthesized This is easy to do grammatically if we change the over-general ClassHeritage : |extends| AssignmentExpression I say over-general because: do we really want this to be valid ES6? class D extends B = C { } Using a higher-precedence expression non-terminal seems better. How about the next lower-precedence nonterminal that does not end in AssignmentExpression, namely LogicalORExpression? Then any yield without parentheses would be a syntax error. /be Allen Wirfs-Brock mailto:al...@wirfs-brock.com November 10, 2013 6:46 PM see bug: https://bugs.ecmascript.org/show_bug.cgi?id=2011 The decision to make the AssignmentExpression optional within a YieldExpression creates an ambiguity when combined with class declarations. For example cosider: function *gen() { class Foo extends yield {} { } } Is the intent for a yield expression that yields a new object or a a yield expression with yields a implicit undefined. Neither a human nor a parser can know for use what the authors actual intent was. There are several ways we could fix this problem: 1) Retract the decision to make the yield assignment expression optional. In this case a 'yield', in all yield expression contexts, would have to always be followed by an explicit expression producing the value to yield. 2) Make the use of 'yield' illegal in the 'extends' clause of class declarations. Arguably this is comparable to the restrictions on the use of 'in' within for-in statements. This would probably not be a major usage issue as actual use cases of 'yield' in that context seems quite implausible. 3) Continue to allow usage of 'yield' expressions in 'extends' clauses but make the AssignmentExpression part of the YieldExpression mandatory in that context. 4) some other, even more ad hoc, disambiguation rule. Either #1 or #2 would be trivial to specify. #2 would be a straight forward use of an expression grammar parameter that we already have. #3 is somewhat harder to specify and requires a new parameter on all of the expression grammar productions. It would require more editorial work to implement and result in a more cluttered grammar definitions. #4 needs an actual proposal that can be evaluated. I would be happy with either alternative #1 or #2. The actual utility of a YieldExpression in an 'extends' clause seems so low that I don't think we should make the entire expression grammar more complicated just to support alternative #3. Thoughts? Allen ___ 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: an idea for replacing arguments.length
On Nov 10, 2013, at 4:53 PM, Brendan Eich wrote: Allen Wirfs-Brock wrote: I think the only sort of declarative overloading that is appropriate for JS is based upon the number of actually passed arguments (and nothing else). Not to pick a fight (yet), but that's a bit strong. Recall I'm proposing value objects with operators dispatching 2-ary functions based on arguments, in a way that is inline-cacheable. Still working on it (Christian Hansen helping), update anon. Sure, but that is dynamic type based dispatching with caching, not static declarative overloading We could do static describe overloads of primitive types (and probably value types). Where the usual attempts at describing overloads for JS go wrong is it they either ignore dynamic coercions or forget in in real JS code they would happen after the overload selection. WebIDL address this by building performing (known) coercions into its overload selection algorithm. But I don't think any human JS programer would do it the way it does. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: optional yield expression creates ambiguity
Brendan Eich wrote: I say over-general because: do we really want this to be valid ES6? class D extends B = C { } Using a higher-precedence expression non-terminal seems better. How about the next lower-precedence Sorry, higher-precedence (jetlag) nonterminal that does not end in AssignmentExpression, namely LogicalORExpression? Another way to go is far higher precedence, say LeftHandSideExpression? That avoids all arithmetic operators, unary and binary. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
Allen Wirfs-Brock wrote: Not to pick a fight (yet), but that's a bit strong. Recall I'm proposing value objects with operators dispatching 2-ary functions based on arguments, in a way that is inline-cacheable. Still working on it (Christian Hansen helping), update anon. Sure, but that is dynamic type based dispatching with caching, not static declarative overloading That it's dynamic does not mean the form used when defining operator multimethods can't be declarative syntax. We need to separate static syntax, which I think is better for defining operators (in classes, value class or regular class), and static overload resolution. Agree we can't have the latter. We could do static describe overloads of primitive types (and probably value types). And *definitely* value types -- or to your dynamic point, value objects. Where the usual attempts at describing overloads for JS go wrong is it they either ignore dynamic coercions or forget in in real JS code they would happen after the overload selection. WebIDL address this by building performing (known) coercions into its overload selection algorithm. But I don't think any human JS programer would do it the way it does. Agreed, although it smells that WebIDL has this kind of overloading at all when JS doesn't. We need to avoid elaborating it, if it is legacy sunk-cost and provided it doesn't infect engines or impose too much hardship on self-hosted overloaded DOM methods, or on JSIDL. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: optional yield expression creates ambiguity
On Sun, Nov 10, 2013 at 5:26 PM, Brendan Eich bren...@mozilla.com wrote: Brendan Eich wrote: I say over-general because: do we really want this to be valid ES6? class D extends B = C { } Using a higher-precedence expression non-terminal seems better. How about the next lower-precedence Sorry, higher-precedence (jetlag) nonterminal that does not end in AssignmentExpression, namely LogicalORExpression? Another way to go is far higher precedence, say LeftHandSideExpression? That avoids all arithmetic operators, unary and binary. If we go with the highest plausible precedence, we can always lower it later. Not vice versa. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
On 11/10/13 5:12 PM, Andrea Giammarchi wrote: I think I've completely missed the `undefined === absent` conversation ... so if I have an object, and `obj.key = void 0` why `key` would be considered absent, exactly? Fwiw, based on feedback from this group this is how WebIDL dictionaries work now: the key is present test is basically obj.key !== undefined as opposed to 'key' in obj... -Boris ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: optional yield expression creates ambiguity
Mark S. Miller wrote: Another way to go is far higher precedence, say LeftHandSideExpression? That avoids all arithmetic operators, unary and binary. If we go with the highest plausible precedence, we can always lower it later. Not vice versa. Yep -- I'm warming up to LeftHandSideExpression. It allows new and call forms, member expressions, primary expressions, but not unparenthesized ternary, binary or unary operators -- and (crucially for the bug) not anything ending in AssignmentExpression. Allen? /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: optional yield expression creates ambiguity
I have heard it argued that await needs higher precedence than we've been considering for yield, but I don't remember the argument. Anyone? Would LeftHandSideExpression be adequate for whatever that argument was? In the future of promises, we will either continue to use yield as await, or we will provide an (essentially synonymous) await. Either way, it would be good for both of these to have the same precedence, and for that precedence to satisfy both needs. On Sun, Nov 10, 2013 at 5:45 PM, Brendan Eich bren...@mozilla.com wrote: Mark S. Miller wrote: Another way to go is far higher precedence, say LeftHandSideExpression? That avoids all arithmetic operators, unary and binary. If we go with the highest plausible precedence, we can always lower it later. Not vice versa. Yep -- I'm warming up to LeftHandSideExpression. It allows new and call forms, member expressions, primary expressions, but not unparenthesized ternary, binary or unary operators -- and (crucially for the bug) not anything ending in AssignmentExpression. Allen? /be -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
On 11/10/13 8:25 PM, Allen Wirfs-Brock wrote: Where the usual attempts at describing overloads for JS go wrong is it they either ignore dynamic coercions or forget in in real JS code they would happen after the overload selection. WebIDL address this by building performing (known) coercions into its overload selection algorithm. But I don't think any human JS programer would do it the way it does. So the way WebIDL works right now is basically a 4-step process: 1) Select the set of valid overloads for the given argument count (basically, select all the overloads that might be callable with that many arguments, based on which arguments they have optional, etc). 2) Do dynamic coercions for arguments starting with the first one and up through the last one on which the elements of this set agree. 3) Select the right overload based on the first argument on which the remaining elements of the overload set disagree. 4) Finish doing dynamic coercions. I agree that this is not how anyone would write this in practice. Part of the reason for this is that this algorithm is trying to handle two types of overloading at once: overloading on argument count (step 1) and overloading on type of argument (step 3). And there are complications from dealing with overloads of the argument type kind in situations where some of the overloads have (typed!) varargs at the end and whatnot, at least in theory. In practice, though, APIs generally do one or the other but not both. To do both you'd need an API somewhat like this (in WebIDL): void foo(); void foo(InterfaceType1 arg); void foo(InterfaceType2 arg); where some overloads have to be told apart by number of arguments and some have to be told apart by the types of the arguments. I just checked for APIs in Gecko's WebIDL where selection is happening based on argument count (in that there are overloads with different argument counts) and there are also some argument counts which have multiple overloads for them. The upshot is that almost all of them can in fact be dealt with by picking an overload based on type of the first argument that doesn't match across all the overloads with just a few exceptions: Document: TouchList createTouchList(Touch... touches); TouchList createTouchList(sequenceTouch touches); IDBFactory: IDBOpenDBRequest open(DOMString name, [EnforceRange] unsigned long long version); IDBOpenDBRequest open(DOMString name, optional IDBOpenDBOptions options); URL: [Constructor(DOMString url, URL base), Constructor(DOMString url, optional DOMString base = about:blank)] interface URL { WebSocket: [Constructor(DOMString url), Constructor(DOMString url, DOMString protocols), Constructor(DOMString url, sequenceDOMString protocols)] XMLHttpRequest: void send(); void send(ArrayBuffer data); void send(ArrayBufferView data); void send(Blob data); void send(Document data); void send(DOMString? data); void send(FormData data); void send(InputStream data); I believe even for all of these, we could treat them as overloads on the type of some argument, where we allow undefined as a type that matches the argument not being present or an argument being optional. So a viable way forward in terms of WebIDL overloads, perhaps, is to simply disallow overloading on both argument count and argument types (modulo the proviso about undefined above, somehow) and require that overloads for a name either all have an argument that can be used to distinguish them from each other or take different argument counts but not both. Or something. This does nothing for getting rid of the need to check arguments.length in overloads that overload on the arg count, of course. We could be more radical and recast it all in terms of examining types, treating missing arguments as undefined but that would break compat in at least canvas methods, unfortunately, and I don't think we _really_ want to go there. On the other hand, what we probably _could_ do if we make the split above is make overloading on arg count explicitly deprecated (e.g. enforce in UAs that no new APIs that use it get added). -Boris ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
RE: optional yield expression creates ambiguity
I believe the argument is that you'd want `await a + b` to be `(await a) + b`, whereas with `yield` it's `yield (a + b)`. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: optional yield expression creates ambiguity
So would LeftHandSideExpression satisfy both needs? I note that this also raises the issue of the precedence of the yield and await expressions themselves. This would argue that the yield expression itself be high precedence. This would not be a decision we could relax later. On Sun, Nov 10, 2013 at 6:15 PM, Domenic Denicola dome...@domenicdenicola.com wrote: I believe the argument is that you'd want `await a + b` to be `(await a) + b`, whereas with `yield` it's `yield (a + b)`. -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: optional yield expression creates ambiguity
Domenic Denicola wrote: I believe the argument is that you'd want `await a + b` to be `(await a) + b`, whereas with `yield` it's `yield (a + b)`. We need a debugged grammar for await, when ready. We have one for yield (existence proofs in several browsers now), and I think we can fix ClassHeritage easily. The reason why yield is low-precedence, at AssignmentExpression level, is to make the observed common case of yield a + b meaning yield (a + b). Python follows the same design, but the design comes from use-case frequency, not directly Python authority. C# 5.0 (http://www.microsoft.com/en-us/download/dlx/thankyou.aspx?id=7029) makes await expression both a statement-expression (the entirety up to the ; terminator of a statement-expresion) and a unary-expression (which cannot be a statement-expression in C# -- but can in JS). If we are copying C#, we can use a lookahead restriction as usual to handle the statement-expression vs. unary-expression cases. We can thus make async a unary prefix operator. You may object: why have the two operators at such different precedence levels. It's a good question, but if we are going by precedent from two different languages, then the answer may be because Blub did it that way. Before we settle for that hash of a design, I'd like to know why C# put async at unary precedence. Maybe Luke knows, or can find out. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: optional yield expression creates ambiguity
Mark S. Miller wrote: So would LeftHandSideExpression satisfy both needs? Mark, LeftHandSideExpression is my proposal for the replacement of AssignmentExpression in ClassHeritage, *not* for anything to do with YieldExpression. I note that this also raises the issue of the precedence of the yield and await expressions themselves. This would argue that the yield expression itself be high precedence. This would not be a decision we could relax later. No, we already have lots of experience with yield, in JS as well as in Python. It's low precedence for good usability reasons (see last post). /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: optional yield expression creates ambiguity
Ok, I withdraw the suggestion. LeftHandSideExpression in ClassHeritage seems good. +1. On Sun, Nov 10, 2013 at 6:34 PM, Brendan Eich bren...@mozilla.com wrote: Mark S. Miller wrote: So would LeftHandSideExpression satisfy both needs? Mark, LeftHandSideExpression is my proposal for the replacement of AssignmentExpression in ClassHeritage, *not* for anything to do with YieldExpression. I note that this also raises the issue of the precedence of the yield and await expressions themselves. This would argue that the yield expression itself be high precedence. This would not be a decision we could relax later. No, we already have lots of experience with yield, in JS as well as in Python. It's low precedence for good usability reasons (see last post). /be -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: optional yield expression creates ambiguity
Brendan Eich wrote: C# 5.0 (http://www.microsoft.com/en-us/download/dlx/thankyou.aspx?id=7029) makes await expression both a statement-expression (the entirety up to the ; terminator of a statement-expresion) s/statement-expresion/expression-statement/ on last line, blargh! /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: optional yield expression creates ambiguity
On Nov 10, 2013, at 5:45 PM, Brendan Eich wrote: Mark S. Miller wrote: Another way to go is far higher precedence, say LeftHandSideExpression? That avoids all arithmetic operators, unary and binary. If we go with the highest plausible precedence, we can always lower it later. Not vice versa. Yep -- I'm warming up to LeftHandSideExpression. It allows new and call forms, member expressions, primary expressions, but not unparenthesized ternary, binary or unary operators -- and (crucially for the bug) not anything ending in AssignmentExpression. Allen? Playing devil's advocate for the movement. Sure, general Expression allows for odd and probably useless things in an extends clause but so does a ParenthesisedExpression so it isn't clear that the LHSExpression restriction really gives JS programmers anything if there is some other way to fix the yield bug. But what the LHSExpression restriction does do is make the language conceptually more complex for programmers. Currently Statement and Declaration forms consistently only use Expression or AssignmentExpression as component elements. And, AssignmentExpression (with one exception, which I think may be a bug. separate issue...) is only used in contexts where there would be a comma based ambiguity. So, taking the language as it stands now, there is really only one concept of expression that JS programmers have to learn and think about when composing JS statements. Restricting the expression in the extends clause of a class definition to LeftHandSideExpression would mean that there is another top-level expression form that is used somewhere in the statement grammar. It's quite likely that some JS programmer will be taught about this but only remember that most places you can use a general expression but some places you can only use some restricted expression form. For that point forward, they may be questioning themselves anytime they write an expression: Is this a place where I have to restrict which operators I use? If we go that route we are trading-off conceptual simplicity against some grammar complexity that most programmer will never see and that only only restricts the YieldExpressions syntax in a manner and place that nobody probably will ever encounter. While it would need to be documented in reference material, no one would really need to be taught about the yield value expression being required in extends clauses. Finally, turns out that restricting the optional yield AssignmentExpression only requires additional parameterization of three productions: Expression, AssignmentExpression, and ConditinalExpression. So, from a conceptual simplicity and consistency perspective, I think it may be better to go with alternative #3 (require AssignmentExpression in YieldExpressions in extends clauses). Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
On Mon, Nov 11, 2013 at 2:12 AM, Allen Wirfs-Brock al...@wirfs-brock.com wrote: One of the the few remaining uses of a function's 'arguments' binding is to determine the actual number of passed arguments. This is necessary in some overloading scenarios where a function has different behavior when an argument is completely absent then it has when undefined (or any other default value) is explicitly passed in that parameter position. That situation occurs in a number of DOM APIs and even a few ES library functions. I think the number is very low. I think I've heard of a total of four DOM functions which currently treat not passed as different from explicitly passed undefined. And we're working on changing those so that the two are treated the same. Unclear if we'll be able to change all of them. So from the DOM point of view, I don't see a lot of reason to add convenience capabilities for detecting that difference. And in none of the cases in the DOM, does function.length become a problem. This is because in all of the cases the argument truly is optional, which means that .length does not include it. So for example for XMLHttpRequest.open you could write a JS implementation that looks like: function open(verb, url, ...args) { let [async, username, passwd] = args; if (args.length == 0) { async = true; } ... more code here ... } It is surprising to me that that is not the case in the ECMAScript APIs, but seems like that is history. / Jonas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
Just to provide another way of working around it: var empty = {}; // or even a symbol? function splice(start = empty, count = 0, ...items) { if (start === empty) { ... } On Mon, Nov 11, 2013 at 1:22 AM, Jonas Sicking jo...@sicking.cc wrote: On Mon, Nov 11, 2013 at 2:12 AM, Allen Wirfs-Brock al...@wirfs-brock.com wrote: One of the the few remaining uses of a function's 'arguments' binding is to determine the actual number of passed arguments. This is necessary in some overloading scenarios where a function has different behavior when an argument is completely absent then it has when undefined (or any other default value) is explicitly passed in that parameter position. That situation occurs in a number of DOM APIs and even a few ES library functions. I think the number is very low. I think I've heard of a total of four DOM functions which currently treat not passed as different from explicitly passed undefined. And we're working on changing those so that the two are treated the same. Unclear if we'll be able to change all of them. So from the DOM point of view, I don't see a lot of reason to add convenience capabilities for detecting that difference. And in none of the cases in the DOM, does function.length become a problem. This is because in all of the cases the argument truly is optional, which means that .length does not include it. So for example for XMLHttpRequest.open you could write a JS implementation that looks like: function open(verb, url, ...args) { let [async, username, passwd] = args; if (args.length == 0) { async = true; } ... more code here ... } It is surprising to me that that is not the case in the ECMAScript APIs, but seems like that is history. / Jonas ___ 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