A syntax alternative for generators (was: Generator issue: exceptions while initializing arguments)

Jason Orendorff jason.orendorff at gmail.com
Wed Sep 12 07:03:50 PDT 2012


Allen, even with all the requirements you listed, I wouldn't write
that example code. There's a more natural way to factor the problem.

> The original example fails for at least the last bullet.  To fix that, it
> would have to be rewritten, something like:
>
> function dataSnapshot(aDataSource) {
>   let snapshot = aDataSource.captureCurrentState();
>   return  function *() {
>      for (let i=0; i<snapshot.length; i++) yield snapshot[i]
>    }
> }

The algorithm for walking the snapshot should be a method of the
snapshot object:

    DataSnapshot.prototype[iterator] = function *() {
        for (let i = 0; i < this.length; i++)
            yield this[i];
    };

Then dataSnapshot could be written in a straightforward way; but in
practice you wouldn't bother, because the function isn't doing
anything useful anymore.

Now for the example using 'this':

> class DataSourceAnalyzer {
>     ...  //a constructor and other methods
>    *dataSnapshot(aDataSource) {
>       let snapshot = aDataSource.captureCurrentState();
>       for (let i=0; i<snapshot.length; i++) yield this.analyzeElement(snapshot[i]);  //  <--- note use of this
>   }
> }

I would write:

    *dataSnapshot(aDataSource) {
        let snapshot = aDataSource.captureCurrentState();
        return [this.analyzeElement(e) for (e of snapshot)];
    }

The behavior is a little different; each element is analyzed eagerly
instead of lazily. That's ordinarily OK; computers are fast. But if
not, you can factor this function into two parts, eager and lazy. Or,
assuming 'this' propagates into generator-expressions, you could just
use parentheses instead of square brackets around the comprehension.

The additional requirements make the example seem more contrived, not
less; and yet even with all that, we're looking at a two-line function
under the current proposal, and the pitfalls never appeared.  This is
what my experience with these features has been like in Python.

When generators are used for iteration, the loc1/loc2 distinction
rarely matters in practice. The generators are typically called from
the RHS of a for-loop, often implicitly, and so the first iter.next()
call comes immediately. loc1 and loc2 are effectively the same.

I think Dave Herman once pursued alternate syntax something like this.
What did he conclude?

-j


More information about the es-discuss mailing list