Removing these inconsistencies would also allow argument and parameter
lists to be explained in terms of desugaring into array structuring
and destructuring patterns respectively:
function(a, , c = 0, ...d){ //...}
would desugar to:
function(){ var [a, , c = 0, ...d] = _arguments_; // even better
would be "let"! //...}
and:
f(a, , c, ...d)
would desugar to:
Function.prototype.apply.call(f, undefined, [a, , c, ...d]);
On Wed, Oct 5, 2011 at 2:19 PM, Sean Eagan <[email protected]> wrote:
> On Mon, Oct 3, 2011 at 4:37 PM, Allen Wirfs-Brock <[email protected]>
> wrote:
>> apply supports holes...
>>
>> f.apply(Array(5));
>>
>> Look at the specification of apply in section 15.3.4.3 of the ES5/5.1 spec.
>> It does a [[Get]] on each element of the argArray to get the value that
>> passed in the argument list. [[Get]] converts holes to undefined.
>
> The only way this is observable in ES5 is if argArray has getters for
> any of the indexes between 0 and argArray.length. I'm not aware of
> any cases of objects defining getters for indexed properties, much
> less those objects being passed to Function.prototype.apply. So the
> only consequence of this is that the hole preservation algorithms in
> the draft spec only call [[Get]] when [[HasProperty]] returns true.
> So we could either tweak the hole preservation algorithm for rest
> parameters to call [[Get]] regardless, or the better option IMHO,
> match the other algorithms by no longer calling [[Get]] for holes in
> argArray, at least when Function.prototype.apply is called from
> extended code.
>
>>
>> syntactic calls will support holes...
>>
>> f(...Array(5))
>>
>> by syntactic calls I meant f(a,b,c). the legacy language does not allow for
>> f(a,,c)
>
> This can be said of any any syntax being added in ES.next. Also, I'm
> only suggesting to add that syntax if it continues to be available in
> array literals.
>
>> What *doesn't* support holes is the `arguments` object which is on its way
>> out.
>>
>> In addition, the specification of the semantics of function invocation made
>> no allowance for the possibility of holes in an argument list.
>>
>> The specification of `arguments` dictates this, not function
>> invocation as a whole.
>>
>> Sorry that is incorrect, see 15.3.4.3
>
> You are correct, sorry. However, this is merely an unobservable
> specification detail, so what relevance does it have to what is best
> for the future of the language ?
>
>> What about holes makes them applicable to arrays in general but not
>> argument arrays ? Everything else in ES.next points to reification of
>> arguments as plain old arrays, why be different here ?
>>
>> Because we aren't talking about reification of arguments. We are talking
>> about the semantics of an argument list in a function call expression and
>> the semantics of the spread operator.
>
> The spread operator in argument lists reifies the argument list as an
> array in my view. But mostly I just care that the semantics are the
> same as when the spread oeprator occurs in an array literal, i.e. that
> holes are preserved for the receiver. If a caller does not want holes
> to be observed by a potential callee rest argument, they can use a
> dense argument list, however I'm not sure why they would care about
> this. If a caller *does* want to allow a potential callee rest
> parameter to utilize holes for optimization purposes, why prevent them
> from doing so?
>
>> I would actually be ok with or without both Elision syntax and hole
>> preservation in ES.next, I just want consistency.
>>
>> One concern that I've already mentioned is that recognizing holes in spread
>> would create an inconsistency with the existing semantics of apply and that
>> changing apply would be a breaking change that might impact existing code.
>>
>> apply does not have existing semantics for rest parameters since they
>> don't yet exist, I'm not suggesting to change the semantics for
>> `arguments` while it's still around
>>
>> Apply is on the caller side. It doesn't have any parameter semantics at
>> all. It is only responsible for passing on a valid argument list.
>> Because apply and normal function application can't depend knowledge to the
>> callee, it is reasonable to expect that:
>> foo.apply(undefined,x)
>> means exactly the same thing as
>> foo(...x)
>>
>
> Yes, I intend for them to mean the same thing, which is that holes in
> x which fall within a range covered by a rest parameter in foo are
> preserved. If foo uses `arguments` they continue to show up as
> undefined values there.
>
>> function f(arg) {
>> [a='a', b='b'] = arg;
>>
>> The above line is not legal syntax according to the current specification
>> draft. The destructuring binding pattern and a destructuring assignment
>> pattern have both different syntax and semantics.
>> In a destructuring binding, a scalar BindingElement is defined as:
>> SingleNameBinding : BindingIdentifier Initializer-opt
>> while in a destructuring assignment, a scalar AssignmentElement is defined
>> as
>> AssignmentElement : LeftHandSideExpression
>> Note that an AssignmentElement does not have an Initializer. The reason I
>> defined it this way is that unlike a BindingIdentifier, a
>> LeftHandSideExpression can be an arbitrary complex expression. I didn't want
>> to allow expressions such as:
>> [new foo.bar[baz(x=5)].bam=0] = obj;
>> where the trailing initializer looks like it is just part of the element
>> expression. I'm willing to discuss the merits of that decision, but the
>> fact remains that the semantics of destructuring binding and destructuring
>> assignment are quite different so I consider suspect any argument that
>> starts by assuming that they are the same.
>
> Sorry, should have read the draft spec more thoroughly, I agree that
> assignment destructuring should have syntactic and semantic
> differences from binding destructuring.
>
> However, I don't see why variable declaration array destructuring
> binding and parameter lists should be different in any way. The only
> current syntactic difference between them is elision:
>
> // allowed
> function f([,,,,,,x]){}
> // disallowed
> function f(,,,,,,x){}
>
> The same syntactic inconsistency exists between array structuring and
> argument lists:
>
> // allowed
> f([,,,,,,x]);
> // disallowed
> f(,,,,,,x);
>
> The only semantic inconsistencies are:
>
> * hole preservation (if function rest parameters do not, but array
> destructuring rest parameters do, as you suggest)
> * default value triggering:
>
> // default not used
> (function(x = 0){})(...[,1])
> // default used
> var [x = 0] = [,1];
>
> To me, eliminating these inconsistencies is a clear win, since it
> eliminates separate syntax and semantics for FormalParameterList and
> ArgumentList in the spec, implementations, and user's minds. I would
> prefer to have elision, hole preservation, and defaulting based on
> input array length rather than holes, but only if they were
> consistently applied.
>
> Thanks,
> Sean Eagan
>
Thanks,
Sean Eagan
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss