Array iterator questions

Allen Wirfs-Brock allen at wirfs-brock.com
Sun Dec 2 12:25:01 PST 2012


On Dec 1, 2012, at 9:58 PM, Brendan Eich wrote:

> Jason Orendorff wrote:
>> 1. The current draft spec has Array.prototype.@@iterator() behaving like .values(), so:
>> 
>>    for (x of ["a"])
>>        print(x);
>> 
>> would print the pair ["0", "a"].
>> 
>> The proposal had Array iterators producing values only by default. Why the change?
> 
> This came up two days ago at the TC39 meeting. It's a drafting error.
> 
>> (It seems like it could be a typo, or it could be motivated by a desire for consistency across all collections. If the latter, Map should change, not Array.)
> 
> There is some desire, which motivated Allen's Array.prototype.{keys,values,items} additions in the latest draft, to have self-polymorphic method dispatch for implementing {keys,values,items}.
> 
> This led to a discussion that concluded by separating the method naming scheme and standard troika (and Andreas Rossberg proposed entries not items, which everyone thought better), from the generic object-reflection function troika that return iterators for property keys, values, and [key, value] pairs. We argued about whether the two name-troikas should match, and I think ended up allowing for this.

A related issue is which iterator to select in various contexts.  For example, if @iterator returns values for arrays and entry key/value pairs for maps then using @iterator may not be the best choice for, for example, processing the argument of Array.from.

Basically, iteration clients need to know what they are asking for.  If you are going to write
    for (i of x) doSomething(x,i);

You better have the expected @iterator behavior of x pretty locked down 

If you known you want "values" and aren't sure of the actual "class" of x then you should probably write:
   for (i of x.values()) doSomething(x,i);

and let it break if x doesn't have a values method.

For things like Array.from and spread, a fall back sequences is a possible approach:
     1) if obj has a "values" method us it to get the iterator
     2) else if obj as a @iterator method use it to get the iterator
     3) else do an array like iteration using the obj's length property value.

I've already been butting into these kinds of situations when specify handling the optional argument to the Map and Set constructors. It's also the reason I have been slow to update the Array.from spec. to handle anything other than array-likes. Map really wants key value pairs so calling @iterator on an Array, if it returns values, isn't what it should do.  However, Set really wants only values.  In general, when dealing with generic collections you can't just use @iterator.  You need to be more explicit about whether you expect to process keys, values, or both.

Allen




More information about the es-discuss mailing list