Enclosed is the first draft of the description of array initializer syntax, which has evolved quite a bit in ES4. The draft feels a little raw, maybe because we have yet to pin down all aspects of how structural array types interact with everything; please read critically and ask difficult questions. (The draft contains an informative section on structural array types as I think they ought to behave.)
--larsTitle: Array initializers
Array initializer syntax
NAME: "Array initializer syntax"
FILE: spec/language/array-literals.html
CATEGORY: Expressions (E262-3 chapter 11)
SOURCES: ES3; REFERENCES [1]-[7]
SPEC AUTHOR: Lars
DRAFT STATUS: DRAFT 1 - 2008-04-08
REVIEWED AGAINST ES3: NO
REVIEWED AGAINST ERRATA: YES
REVIEWED AGAINST BASE DOC: NO
REVIEWED AGAINST PROPOSALS: NO
REVIEWED AGAINST CODE: NO
REVIEWED AGAINST TICKETS: YES
IMPLEMENTATION STATUS: ?
TEST CASE STATUS: ?
OPEN ISSUES
* A splicing shorthand has been introduced for ES4 array
initializers. In order to be compatible with other uses of the
same syntax (destructuring, rest arguments, the spread operator)
only one splice is allowed. That may be a foolish consistency.
REFERENCES
[1] proposals:structural_types_and_typing_of_initializers
[2] ES4 base document
[3] Ticket #66
[4] Ticket #120
[5] Ticket #249
[6] Ticket #319
[7] Ticket #370
Synopsis
This draft pulls together everything that has been proposed and tentatively agreed about array initializer syntax and semantics.
Primary syntax
In its general form an array initializer is comprised of an
optional keyword (const or var), followed by a
bracket-delimited comma-separated list of optional expressions with
the last _expression_ optionally followed by a triple-period token and a
final _expression_, followed by an optional type annotation.
[ "const" | "var" ] "[" Body "]" [ ":" Type ]where Body is one of
AssignmentExpression? ( "," AssignmentExpression? )* ( AssignmentExpression? "," )* "..." AssignmentExpression
The "Type" that annotates the initializer must be a structural array type or a nominal class type whose constructor accepts zero arguments.
Creating Array objects
If the annotating type is absent, or if the annotating type is a structural array type, then the following rules apply.
NOTE Some informative remarks about structural array types are included at the end of the document.
As in ES3, an elided _expression_ leaves a hole in the array (by the same syntactic rules, not repeated here).
NOTE The value of a hole can be read provided the type of the hole
has a default value (as do primitive string, number, and boolean
values as well as nullable object types and the "any" type *).
The details are defined by another draft spec but there are some
informative comments in the later section on structural array types.
The final optional _expression_ of the form ... E evaluates
E to yield some object v and splices some properties of v
into the new array object. v need not be an instance of
Array, but it needs to provide a value for length and to allow
elements with names in the range 0 to length-1 (suitably
clamped) to be queried for their presence and, if present, to be read.
If a property with a name n in that range is missing from v
then the property in the new object that v[n] would have
initialized will be a hole.
FIXME The above needs to be formalized properly, obviously.
If the array initializer is prefixed by const or var then
the array properties created will be created as fixtures; if the
prefix is const those fixtures will additionally be read-only.
The general form of Type is [T0,
,Tk,...Tr] where
T0 through Tk (the fixed types) and Tr (the rest
type) are all optional. The initializer must provide a (possibly
elided) value for each of T0 through Tk, and may provide
additional values only if Tr is present.
NOTE If the initializer is prefixed by const or var, or if
there are types T0 through Tk present in the type, then array
elements can still be elided from the initializer and there can be
holes in any spliced-in object. However, the missing properties will
be present as uninitialized fixtures on the object, not as missing
dynamic properties. So
1 in [1,,3]:[double,double,...double] will
return true. A longer discussion is included below, in the
section on structural array types.
Creating arbitrary objects with numbered properties
If the annotating type is a class type whose constructor accepts
zero arguments then the const and var keywords must not be
present.
In this case, the _expression_ evaluates to a new instance of the
class type where successive initializer values have been assigned to
numbered properties of the new object and the length of the
initializer has been assigned to the length property of the new
object.
In other words,
[1,,3,,] : Vector.<double>
is syntactic sugar for
(let (TMP = new Vector.<double>)
(TMP[0] = 1,
TMP[2] = 3,
TMP.length = 4,
TMP))
for a fresh variable TMP.
Secondary syntax
Suppose T is a structural array type:
type T = [...double]
Then the new operator can be used as follows:
new T( 10 ) new T( 5, 1.0 )
The meaning of the above two phrases is exactly:
[,,,,,,,,,,] : T [1.0, 1.0, 1.0, 1.0, 1.0] : T
In other words, used with a structural array type the new
operator takes one or two arguments. The first argument is always the
length. The second argument, if present, is the initial value to use
for the properties at indices below the length.
NOTE The array type can be of any kind: with or without fixed types or a rest type.
Rationale
This section is informational and will not be part of the finished Standard.
The splicing syntax is symmetric with the prefix ... syntax in
in destructuring array patterns:
var [x,y,...z] = E
To remain compatible with the destructuring syntax, the splicing syntax is only allowed at the end of the literal -- it doesn't make sense to have an open destructuring pattern in the middle of a pattern.
However, that may be taking compatibility too far, as there are obvious uses for having multiple splices (just as there are uses for allowing multiple spread operators in a function call).
The new syntax furthers the evolutionary programming agenda
and is yet another point on the continuum between ES3 programs and
class-based ES4 programs (the syntax abstracts away from the type T
that is the subject of new -- whether it's a class or a structural
type). For example,
type Doubles = [...double] new Doubles(10)evolves easily to
type Doubles = Vector.<double> new Doubles(10)
Nominal type annotations on array initializers further the evolutionary programming agenda, allowing programs that use structural array types as annotations on literals to be changed easily to use class types instead. For example,
type Doubles = [...double] [1,2,3]:Doublesevolves easily to
type Doubles = Vector.<double> [1,2,3]:Doubles
In addition, [1,2,3]:Vector.<double> is by itself a
fairly reasonable way to write down a vector datum.
Structural array types
This section is informational; a separate spec will explain array types in detail.
A structural array type is comprised of some possibly empty
sequence of fixed types T0 through Tk followed by an
optional rest type Tr. Elements in the type can be elided;
elided elements default to the "any" type *.
"[" ( Type? "," )* ("..." Type)? "]"
Examples:
[...double] /* doubles, length >= 0 */
[string, ...double] /* one string followed by doubles; length >= 1 */
[string, double] /* one string and one double, length = 2 */
[string, , string] /* [string, *, string] */
[] /* length = 0 */
An object v is said to be of an array type T if v is
an instance of (a subtype of) Array and has the fields required by
T. That is, if T is [T0,
,Tk,...Tr] then v must have
fixed type constraints T0 through Tk on properties named 0 through
k, and a general constraint Tr on properties named k+1
through 232-2.
The fixed type constraints are handled by means of fixtures: fields named 0 through k are fixtures. The general constraint Tr on the other hand applies to dynamic properties.
Effectively (and making use of some imaginary syntax), we can say that
[string, double, ...boolean]is essentially this record type:
{ 0: string, 1: double, 2...: boolean, length: double }
(apart from a lot of methods defined on Array objects).
This split between fixture and dynamic properties looks like it could cause trouble, but as it happens it will not.
The reason is that it could cause trouble is that there is a two-pass name lookup algorithm that gives priority to fixture properties, and that means that in the above object the property 1 and the property 2 would be treated differently though both are logically array properties. That would seem bizarre.
The reason that it does not cause problem in practice is that the
difference between fixture and dynamic properties is not observable in
an object that has been created by annotating array initializers with
a structural array type. Such an object would have
Array.prototype as its [[Prototype]] and it's not possible for the
program to introduce new fixtures on the prototype object. In other words, the
array objects created this way have strictly more fixtures than all
the objects in their prototype chains. Thus the two-pass name lookup
algorithm will never find a fixture in a prototype that in effect
shadows a dynamic, index-named property in the object itself.
The final wrinkle (alluded to earlier) is that fixture properties may be elided from the initializer. For example, consider this object:
["foo", ,] : [string, double]
The property "1" can't be missing, because the type requires that
it be there: the object "is of that type", so by definition the
property "1" must always exist, and the type of that property must
always be double. For a property to "have a type" (other than a
rest type) is to be a fixed property.
There is a simple interpretation for this (also alluded to earlier): the property is in the object, but it is uninitialized. If the type of the property has a default value, then that value is produced when the property is read. Otherwise, the property cannot be read before it has been written (or a run-time error occurs). That happens for instances of non-nullable user-defined classes.
_______________________________________________ Es4-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es4-discuss
