@@iterator in arguments object
On Sat, Dec 22, 2012 at 4:57 PM, Nathan Wall <nathan.wall at live.com> wrote:
I never fully understood why the arguments object couldn't be an array, and I know there is at least an attempted purge of the arguments object from the language with the addition of rest parameters.. But, for the transitional period, can the arguments object have an @@iterator property? Please??
Yes
(I looked for it in the draft and didn't see it, but I might not have known where to look.)
Likely because Allen had enough on his plate for this draft, but there is already a ticket based on a resolution from the last TC39 meetng: ecmascript#1114
That's great news! Thank you!
Nathan
It's good this will be added (no reason not to) but I'll note that is much less of a requirement to even use the arguments object at all, especially iteration use cases that are pretty much filled by rest. In fact (almost?) the only place I've actually referenced the arguments object is to count the number of arguments to differentiate between deliberate undefined and a missing argument (and only for that use in order to match the behavior of how js engines treat the arguments to some string built-ins).
Parameter default values weren't good enough for this?
[[[Sent from a mobile device. Please forgive brevity and typos.]]]
Dr. Axel Rauschmayer axel at rauschma.de Home: rauschma.de Blog: 2ality.com
You're right, defaults would take care of those few places reducing the
need to reference the arguments object entirely. I think there may be one
or two exceptions, like when there's no default value but an explicit
undefined
is coerced to "undefined" but a lack of the argument becomes an
empty string. I guessable default value of the empty string may cover this
but I have a nagging feeling there's some exception in one of the builtin
methods that defies all attempts that don't rely on arguments.length, but I
can't figure out what that method might be.
Brandon Benvie wrote:
You're right, defaults would take care of those few places reducing the need to reference the arguments object entirely. I think there may be one or two exceptions, like when there's no default value but an explicit
undefined
is coerced to "undefined" but a lack of the argument becomes an empty string. I guessable default value of the empty string may cover this but I have a nagging feeling there's some exception in one of the builtin methods that defies all attempts that don't rely on arguments.length, but I can't figure out what that method might be.
If it exists, it's just bad precedent.
You could always use an explicit rest parameter as the only formal parameter and still dispense with arguments in new code. So let's say s/could/should/.
Yeah good point, and you don't even need to dump all the named params. In light of this, I think its feasible to pronounce the arguments object in ES6 as vestigial and ready for retirement (except for all the legacy code of course). ES6 claims another victim: [object Arguments].
On Dec 23, 2012, at 9:38 AM, Brendan Eich wrote:
Brandon Benvie wrote:
You're right, defaults would take care of those few places reducing the need to reference the arguments object entirely. I think there may be one or two exceptions, like when there's no default value but an explicit
undefined
is coerced to "undefined" but a lack of the argument becomes an empty string. I guessable default value of the empty string may cover this but I have a nagging feeling there's some exception in one of the builtin methods that defies all attempts that don't rely on arguments.length, but I can't figure out what that method might be.If it exists, it's just bad precedent.
You could always use an explicit rest parameter as the only formal parameter and still dispense with arguments in new code. So let's say s/could/should/.
And you can then use destructuring assignment to parse out that rest parameter into one or more signature patterns.
Arguments object is used here to fill the rest void, but also as an argument to apply (after converting into a real array) when writing wrapper functions; eg monkey patches, userspace profiling, etc.
Is there an ES6 way to use apply on rest params? If not, arguments must live on.
Sent from my iPhone
On 2012-12-23, at 12:48, Brandon Benvie <brandon at brandonbenvie.com> wrote:
Yeah good point, and you don't even need to dump all the named params. In light of this, I think its feasible to pronounce the arguments object in ES6 as vestigial and ready for retirement (except for all the legacy code of course). ES6 claims another victim: [object Arguments].
Something like this?
var partial = (fn, ...args) => function(...newArgs){ return fn.apply(this, args.concat(newArgs)); };
Wes Garland wrote:
Arguments object is used here to fill the rest void, but also as an argument to apply (after converting into a real array) when writing wrapper functions; eg monkey patches, userspace profiling, etc.
Is there an ES6 way to use apply on rest params?
A rest parameter is a real Array instance. Function.prototype.apply works on array instances. What's the problem?
As of ES5, apply doesn't require its 2nd arg to be a "real array". An arguments object works fine there.
Here's one of the examples that was sticking out in my mind earlier that Brendan's solution takes care of. Array.prototype.reduce requires that if the initial value isn't provided then the first value of the array is the initial value.
Using rest:
function reduce(callback, ...initial){
var current, index;
if (initial.length) {
index = 0;
current = initial[0];
} else {
index = 1;
current = this[0];
}
...etc...
}
Using arguments.length:
function reduce(callback, initial){
var current, index;
if (arguments.length > 1) {
index = 0;
current = initial;
} else {
index = 1;
current = this[0];
}
...etc...
}
I guess using rest like that is not a bad way to solve it, though it's not saying what you mean but rather kind of hacking around the limitation. Either way, it's certainly possible to forgo using arguments to accomplish the goal.
On Sun, Dec 23, 2012 at 1:26 PM, Wes Garland <wes at page.ca> wrote:
Arguments object is used here to fill the rest void, but also as an argument to apply (after converting into a real array) when writing wrapper functions; eg monkey patches, userspace profiling, etc.
Is there an ES6 way to use apply on rest params? If not, arguments must live on.
There is something really nice. You can use the ... operator when calling a function. For example, if you're wrapping a function foo:
_origFoo = foo; foo = function (a, b, ...rest) { // ... do something ... return _origFoo(a, b, ...rest); };
If you're wrapping a method it's not quite as nice, but:
_origMethod = Bar.prototype.method; Bar.prototype.method = function (a, b, ...rest) { // ... do something ... return _origMethod.call(this, a, b, ...rest); };
On Sun, Dec 23, 2012 at 8:35 PM, Brandon Benvie <brandon at brandonbenvie.com>wrote:
Here's one of the examples that was sticking out in my mind earlier that Brendan's solution takes care of. Array.prototype.reduce requires that if the initial value isn't provided then the first value of the array is the initial value.
Using rest:
function reduce(callback, ...initial){ var current, index; if (initial.length) { index = 0; current = initial[0]; } else { index = 1; current = this[0]; } ...etc... }
Using arguments.length:
function reduce(callback, initial){ var current, index; if (arguments.length > 1) { index = 0; current = initial; } else { index = 1; current = this[0]; } ...etc... }
I guess using rest like that is not a bad way to solve it, though it's not saying what you mean but rather kind of hacking around the limitation. Either way, it's certainly possible to forgo using arguments to accomplish the goal.
In the case of reduce, the specification algorithm names an identifier in the formal parameter list: initialValue, so what is preventing your implementation from doing initial !== undefined?
Because initialValue can be a provided undefined
in which case you would
use that, as opposed to a missing value. The specification differentiates
between a provided undefined and a lack of a parameter in a bunch of stdlib
functions/methods.
Er missing argument. The spec says "If an initialValue was provided in the call to reduce, ...". The fact that undefined is different from "not provided" is the reason you have to hack around with the argument count one way or another.
On Dec 23, 2012, at 5:35 PM, Brandon Benvie wrote:
Here's one of the examples that was sticking out in my mind earlier that Brendan's solution takes care of. Array.prototype.reduce requires that if the initial value isn't provided then the first value of the array is the initial value.
Using rest:
function reduce(callback, ...initial){ var current, index; if (initial.length) { index = 0; current = initial[0]; } else { index = 1; current = this[0]; } ...etc... }
Using arguments.length:
function reduce(callback, initial){ var current, index; if (arguments.length > 1) { index = 0; current = initial; } else { index = 1; current = this[0]; } ...etc... }
I guess using rest like that is not a bad way to solve it, though it's not saying what you mean but rather kind of hacking around the limitation. Either way, it's certainly possible to forgo using arguments to accomplish the goal.
the way I would express this example is:
function reduce(callback, ...rest){ var current, index; if (rest.length > 0) { index = 0; current = rest[0]; } else { index = 1; current = this[0]; } ...etc... }
which seems to exactly express the intent
On Sun, Dec 23, 2012 at 9:25 PM, Brandon Benvie <brandon at brandonbenvie.com>wrote:
Because initialValue can be a provided
undefined
in which case you would use that, as opposed to a missing value. The specification differentiates between a provided undefined and a lack of a parameter in a bunch of stdlib functions/methods.
True enough: "is present", used in reduce, reduceRight, Object.create and then elsewhere in the abstract internals and then in different contexts.
How about the following solution?
let missingArgument = {}; // or a symbol
function reduce(callback, initial = missingArgument){
let startIndex;
if (initial === missingArgument) {
initial = this[0];
startIndex = 1;
} else {
startIndex = 0;
}
...etc...
}
That is an excellent solution!
Thanks. The first let
should be a const
.
Won't work for an explicitly pass undefined because that triggers assignment of the default value
Ah yes, so default value can't do the job in any case where undefined is differentiated from missing, similar to how directly comparing the named binding to undefined can't differentiate either.
Ah damn, forgot about that discussion (combinatorial explosion etc.).
Welcome to my life...
On Sun, Dec 23, 2012 at 10:46 PM, Axel Rauschmayer <axel at rauschma.de> wrote:
How about the following solution?
let missingArgument = {}; // or a symbol function reduce(callback, initial = missingArgument){ let startIndex;
An explicit undefined will trigger the default value, in this case resulting in the missingArgument to be used
I never fully understood why the arguments object couldn't be an array, and I know there is at least an attempted purge of the arguments object from the language with the addition of rest parameters.. But, for the transitional period, can the arguments object have an @@iterator property? Please??
(I looked for it in the draft and didn't see it, but I might not have known where to look.)
Nathan