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 <seaneag...@gmail.com> wrote:
> On Mon, Oct 3, 2011 at 4:37 PM, Allen Wirfs-Brock <al...@wirfs-brock.com> 
> 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
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to