Standard @iter module unfriendly to collection builders

Allen Wirfs-Brock allen at
Sat Nov 12 11:26:30 PST 2011

The Iterators proposal includes the definition ( ) of functions that are intended to support various common iteration patterns.

For example,   

  for ((k of keys(x)) { ...}
  for (v of values(x)) { ...}
  for ([k,v] of items(x)) {...}
  for (k of allKeys(x)) { ...}
  for (k of allValues(x)) { ...}
  for (i of allItems(x)) { ...}

The use of these functions seems to be pretty much an essential part of the intended use of the for-of statement.  

Most  object-oriented framework designer would immediately see a flaw in this design.  keys, values, items, etc. are all functions that incorporate into them a specific collection element storage model.  This makes it impossible to use them with new collections that uses a different storage model.  For example, they would not work over a binary tree based collection. 

In providing better forms of iteration for the language, it is important that we do not box it into a specific collection implementation.  We want ES to be a first tier language that fully supports the creation of rich collection abstractions with a broad range of functional and performance trade-off.

Operations, such as these iteration functions need to be dynamically dispatched, based upon the type of collection they are applied to. A OO designer would simply avoid this problem by replacing these functions with methods (or getter properties):

  for ((k of x.keys) { ...}
  for (v of x.values) { ...}
  for ([k,v] of x.items) {...}
  for (k of x.allKeys) { ...}
  for (k of x.allValues) { ...}
  for (i of x.allItems) { ...}

However, some may find this formulation less attractive or have other reasons to prefer a functional formulation.  If we perfer to adopt the functional formulation, then it should be done in  a manner that does the necessary dynamic dispatch.  For example:

  export function keys(obj) {
       return {
           [iterator]: function(() {return obj.keys}

Note that if there was a concern about property name conflicts with "keys", "values", etc. and the data storage keys of property access based collections, then built-in private names should be specified instead of these names for the corresponding method/getter property names.

There might also be a concern that this forces all collection implementors to code these iterator methods.  That issue could be avoided by defining the built-in functions to conditionally check for the corresponding methods of the collection object and to fall back to a default implementation.  However, it isn't obvious that the property based backing store is the best long term default for collections.


A different issue: it isn't clear why the distinction between own and inherited properties are built into these iterator functions.  This is not a distinction that would apply to many new collection abstractions. 

 Even if it is a useful distinction,making "own property" iteration be the default seems wrong.  The inheritance structure of an object should be an object implementation issue, not an object client usage issue. 

For example, whether a call:
    let collection = (new Collection("a",1,"b",2,"c",3)).update("a",4");
results in an object that looks like {a:4,b:2,c:3} or an object that looks like {a:1,b:2,c:3}<|{a:4} should not be relevant to most clients. 

We are putting lots of energy into trying to support better object-oriented abstraction capabilities, up to and including class literals. We should also be making sure that the other features we add to also support good object-oriented design principles.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the es-discuss mailing list