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