Re: an idea for replacing arguments.length
How Function.getArguments()? Function.getArguments() should return the arguments array. let args = Function.getArguments(); if(args.length != 2) throw new Error(invalid arguments); -- View this message in context: http://mozilla.6506.n7.nabble.com/an-idea-for-replacing-arguments-length-tp298172p299750.html Sent from the Mozilla - ECMAScript 4 discussion mailing list archive at Nabble.com. ___ 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: Also, I would outlaw (new) overloads like Document: TouchList createTouchList(Touch... touches); TouchList createTouchList(sequenceTouch touches); Yeah, why are *new* (this is from Web Events, not legacy) APIs doing the crazy. Answer: because people imitate older crazy APIs, and WebIDL supports this. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
On 11/12/13 11:24 AM, Brendan Eich wrote: Yeah, why are *new* (this is from Web Events, not legacy) APIs doing the crazy. Answer: because people imitate older crazy APIs, and WebIDL supports this. No. In this case it's because the spec started out one way (with the sequence, iirc) but then got changed to the other way, but implementations had already shipped the first way, so now for compat they support both. If webidl didn't allow this, they'd just use any... and define it all in prose, I assume. -Boris ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
On 11/12/13 12:21 PM, Brendan Eich wrote: Oh, ok -- new-ish legacy. This makes the case for stronger normative specs against such overloading, starting with WebIDL. Again, WebIDL disallowing this would not have helped; the real issue was a semantic problem. I'm all for simplifying the overloading that WebIDL supports, but it wouldn't have affected this case. -Boris ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
Boris Zbarsky wrote: Oh, ok -- new-ish legacy. This makes the case for stronger normative specs against such overloading, starting with WebIDL. Again, WebIDL disallowing this would not have helped; the real issue was a semantic problem. What semantic problem required two createTouchList functions having the same name? Isn't that a design choice? If so, then I am arguing it was the wrong choice, but looked ok by precedent including WebIDL support. I'm all for simplifying the overloading that WebIDL supports, but it wouldn't have affected this case. Whatever I'm trying to affect, the idea is norms, not outright bans or removals of code required for backward compatibility. If createTouchList is relatively new, then I bet there will be a next time. What spec of doc should promulgate a norm that says use a different name for the second createTouchList? /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
On 11/12/13 7:19 PM, Brendan Eich wrote: What semantic problem required two createTouchList functions having the same name? The fact that some UAs shipped one version of it others shipped another (as the spec evolved), then the working group decided to spec one of those versions but there was already code in the wild using the other version, so those UAs are now just supporting both signatures to avoid breaking that code. Isn't that a design choice? Sure. A bad one; the working group should have changed the name when they changed the semantics. If so, then I am arguing it was the wrong choice, but looked ok by precedent including WebIDL support. It didn't look ok. They just made a backwards-incompatible change, period. Whatever I'm trying to affect, the idea is norms Sure. My point is that in this particular case the norm of overloads in WebIDL wasn't the real norm that got broken. The don't break shipping stuff norm was the real issue. What spec of doc should promulgate a norm that says use a different name for the second createTouchList? You mean don't effing randomly break backwards compat? No spec for that, sadly. -Boris ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
On 11/11/13 1:22 AM, Jonas Sicking wrote: 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. This is not true at all. You're thinking of the few cases that have a optional boolean foo = true argument but depend on explicit undefined being treated as false. And even there we know for a fact that we can't change at least one of then (XMLHttpRequest.open). But there are more APIs that treat not passed as different from undefined that don't involve default values. CanvasRenderingContext2D.drawImage is a prime example. So, I suspect, is CanvasRenderingContext2D.putImageData. Probably others too; I haven't done an exhaustive search. So from the DOM point of view, I don't see a lot of reason to add convenience capabilities for detecting that difference. Well, to the extent that we're not self-hosting the DOM implementation, sure. I mean, for the specific case of SpiderMonkey we get an args.length() no matter what in a JSNative, so obviously we don't have to care too much about whether that's possible in the language itself from that point of view. But that seems a bit shortsighted to me. And in none of the cases in the DOM, does function.length become a problem. Well, largely because that's so busted in DOM implementations and specs anyway. ;) -Boris ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
That is excellent! Has all the upsides of the best of the other proposals and none of the downsides. On Sun, Nov 10, 2013 at 11:33 PM, Corey Frang gnar...@gmail.com wrote: 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 -- 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 11, 2013, at 6:10 AM, Mark S. Miller wrote: That is excellent! Has all the upsides of the best of the other proposals and none of the downsides. On Sun, Nov 10, 2013 at 11:33 PM, Corey Frang gnar...@gmail.com wrote: 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) { ... } No, this doesn't work because then both [1,2,3].splice() [1.2.3].splice(undefined) will both result in start === empty. But for web compatibility they must be treated differently. 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 9:21 AM, Allen Wirfs-Brock al...@wirfs-brock.com wrote: On Nov 11, 2013, at 6:10 AM, Mark S. Miller wrote: On Sun, Nov 10, 2013 at 11:33 PM, Corey Frang gnar...@gmail.com wrote: 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) { ... } That is excellent! Has all the upsides of the best of the other proposals and none of the downsides. No, this doesn't work because then both [1,2,3].splice() [1.2.3].splice(undefined) will both result in start === empty. But for web compatibility they must be treated differently. Right. The one and only way to test for missing args different from undefined is to use a rest arg and test length, as demonstrated earlier in this thread. ~TJ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
Doh! My mistake. I was momentarily attributing the old semantics to default parameter assignment, in which case we wouldn't have had the problem in the first place. On Mon, Nov 11, 2013 at 9:21 AM, Allen Wirfs-Brock al...@wirfs-brock.comwrote: On Nov 11, 2013, at 6:10 AM, Mark S. Miller wrote: That is excellent! Has all the upsides of the best of the other proposals and none of the downsides. On Sun, Nov 10, 2013 at 11:33 PM, Corey Frang gnar...@gmail.com wrote: 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) { ... } No, this doesn't work because then both [1,2,3].splice() [1.2.3].splice(undefined) will both result in start === empty. But for web compatibility they must be treated differently. Allen -- 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 6:12 PM, Boris Zbarsky wrote: ... 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). My, perhaps more radical, recommendation would be to only do overloading based upon argument counts and to treat all type overloads for a given argument length as union types that are left to a function's implementation to discriminate. That would vastly simplify the WebIDL overload dispatch and pretty much eliminate the idea that WebIDL based methods must be exotic objects with distinctive [[Call]] behavior. Also, I would outlaw (new) overloads like Document: TouchList createTouchList(Touch... touches); TouchList createTouchList(sequenceTouch touches); In the general case in JS code it can be quite problematic to distinguish these and hence this pattern really should be used. There is much regret about the main place this pattern occurs in the ES built-ins: var a = new Array(1,2,3); //create a three element array with with elements initialized to 1,2,3 var b = new Array(1); //create a sparse array whose length is set to 1; Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
On 11/11/13 1:37 PM, Allen Wirfs-Brock wrote: My, perhaps more radical, recommendation would be to only do overloading based upon argument counts and to treat all type overloads for a given argument length as union types that are left to a function's implementation to discriminate. We could do that, in fact; the problem becomes how to handle the few cases I listed in my mail. pretty much eliminate the idea that WebIDL based methods must be exotic objects with distinctive [[Call]] behavior. I don't see how it changes anything in this regard, actually. Also, I would outlaw (new) overloads like Document: TouchList createTouchList(Touch... touches); TouchList createTouchList(sequenceTouch touches); Sure. This one is fallout from the spec changing from one of those to the other but people not wanting to break compat so supporting both... I don't think anyone _likes_ to create an API like that. var a = new Array(1,2,3); //create a three element array with with elements initialized to 1,2,3 var b = new Array(1); //create a sparse array whose length is set to 1; This is actually a different pattern from the createTouchList one above, though I agree it's equally undesirable. -Boris ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
I hate to bring this up, as I'm sure I've missed a bunch of the arguments that define WHY, but if this is the case, it seems unintuitive to me that passing undefined still results in a default param being set. function test(a = 1) { console.log(a); } test(); // gets 1 - yay test(undefined); // gets 1 - boo! Expect: undefined (sorry tab, forgot to reply all on the first reply :( ) On Mon, Nov 11, 2013 at 12:37 PM, Tab Atkins Jr. jackalm...@gmail.comwrote: On Mon, Nov 11, 2013 at 9:21 AM, Allen Wirfs-Brock al...@wirfs-brock.com wrote: On Nov 11, 2013, at 6:10 AM, Mark S. Miller wrote: On Sun, Nov 10, 2013 at 11:33 PM, Corey Frang gnar...@gmail.com wrote: 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) { ... } That is excellent! Has all the upsides of the best of the other proposals and none of the downsides. No, this doesn't work because then both [1,2,3].splice() [1.2.3].splice(undefined) will both result in start === empty. But for web compatibility they must be treated differently. Right. The one and only way to test for missing args different from undefined is to use a rest arg and test length, as demonstrated earlier in this thread. ~TJ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
On 11/11/2013 11:31 AM, Corey Frang wrote: I hate to bring this up, as I'm sure I've missed a bunch of the arguments that define WHY, but if this is the case, it seems unintuitive to me that passing undefined still results in a default param being set. function test(a = 1) { console.log(a); } test(); // gets 1 - yay test(undefined); // gets 1 - boo! Expect: undefined (sorry tab, forgot to reply all on the first reply :( ) The reason for this is so that you can do: ```js function foo(bar) { return delegatedFoo(foo, bar); } function delegatedFoo(foo, bar = bar) { return foo + bar; } foo(); // foobar and not fooundefined ``` This kind of argument-passing delegation is a very common in JS. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: an idea for replacing arguments.length
Sure, it makes some sense when you see it like that :) I retract my this doesn't make sense I guess we are stuck with (...args) On Mon, Nov 11, 2013 at 2:37 PM, Brandon Benvie bben...@mozilla.com wrote: On 11/11/2013 11:31 AM, Corey Frang wrote: I hate to bring this up, as I'm sure I've missed a bunch of the arguments that define WHY, but if this is the case, it seems unintuitive to me that passing undefined still results in a default param being set. function test(a = 1) { console.log(a); } test(); // gets 1 - yay test(undefined); // gets 1 - boo! Expect: undefined (sorry tab, forgot to reply all on the first reply :( ) The reason for this is so that you can do: ```js function foo(bar) { return delegatedFoo(foo, bar); } function delegatedFoo(foo, bar = bar) { return foo + bar; } foo(); // foobar and not fooundefined ``` This kind of argument-passing delegation is a very common in JS. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
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
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: 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: 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: 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: 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: 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: 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: 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: 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