On Sep 9, 2012, at 3:32 PM, Brendan Eich wrote:

> I wanted to leave a clean example (no var and let mixing, either):
> 
> function dataSnapshot(aCollection) {
>  let snapshot = aCollection.clone();
>  let i = 0;
>  return {
>    next: function () {
>      if (i == snapshot.length)
>        throw StopIteration;
>      return snapshot[i++];
>    }
>  };
> }
> 
> (I usually prefer post-increment for loop-ish constructs. Old C hacker here.)
> 
> Again, anyone trying to avoid the .clone() call would be disappointed. Anyone 
> trying to avoid the extra level of function nesting would be disappointed. 
> There is irreducible complexity here.
> 
> But the generator form is still winning:
> 
> function dataSnapshot(aCollection) {
>  let snapshot = aCollection.clone();
>  return function*() {
>    for (let i = 0; i < snapshot.length; i++){
>      yield snapshot[i];
>    }
>  }();
> }
> 

What's going on here seems clearer to me, if I think about a generator as a 
unusual kind of constructor rather than an unusual kind of function that can be 
suspended and resumed.   From that perspective a call to the generator is 
really a "constructor called as a function" that implicitly does a new, much 
like several other built-in constructors.  Thinking about it that way, you 
might alternatively write your dataSnapshot function as:

function dataSnapshot(aCollection) {
 let snapshot = aCollection.clone();
 return new function*() {
   for (let i = 0; i < snapshot.length; i++){
     yield snapshot[i];
   }
 };
}

Is new'ing generators intended to be legal?

Instances of generators are iterator objects that implement a state machine 
based upon the code provided as the body of the constructor. I shouldn't be 
thinking about the call to the generator as returning a suspended function 
activation, instead I should be think of it as simply return an object that 
implements the iterator interface.

My concern about concise generator method syntax is that it makes the 
generator-ness of the method appear to be an important part of the class 
instance interface when it should really be an implementation detail.  Consider 
as class such as:

class DataCollection extends Collection {
   *@iterator() {
           ... //implementation details
     }
}

The interface of this class should be described as having an @iterator method 
that returns an object that implements the abstract iterator interface.  
Whether that object is an instance of a generator or a non-generator based 
iterator object shouldn't be relevant to clients of this class.  It's an 
implementation detail that can be subject to change within impacting clients.   
However, the appearance of * as the first character of the method definition 
gives it an unjustified importance.  I might actually prefer the above written 
as:

class DataCollection extends Collection {
   @iterator() {
           return new function*() {
                  ... //implementation details
            }
     }
}

Allen




_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to