Check out Dart's iterators

Oliver Hunt oliver at apple.com
Sun Feb 10 13:37:41 PST 2013


On Feb 10, 2013, at 1:01 PM, David Bruant <bruant.d at gmail.com> wrote:

> Le 10/02/2013 20:55, Oliver Hunt a écrit :
>> Just a couple of questions on this wonderous topic:
>> 
>> * how is 'e instanceof StopIteration' intended to work across multiple global objects?
> StopIteration has a special "StopIteration" [[Brand]] [1], so the cross-global story shouldn't be a problem for the for-of loop.
> Exposing the brand can solve the problem for manual use of iterators. (you'd check if the object has a particular brand instead of "e instanceof StopIteration").
> 
> StopIteration could also be a deeply frozen constructor with same identity across globals.
> 
>> * how firmly are we wedded to this? I can't imagine there is too much code that currently depends on manually catching StopIteration given ES6 is not finalized yet, and iterators aren't widely available.
>> 
>> I do dislike the exception based termination, I _think_ i'd prefer next() and hasNext() style iteration over exceptions, especially given that for the most part these are hidden by clean syntax.
> The "for the most part these are hidden by clean syntax" argument applies to throwing StopIteration too, no?

Yes, but exception handling for control flow is generally problematic, and you end up with things like:

function foo() {
    try {
       ...
       yield ...
       ...
    } catch(...) { }
}

Maybe this will be caught, maybe it won't.  If we say that yield acts as an exception (eg. manual iteration is performed via catch()) then the _intuition_ is that the exception handler will break yield.

You get other things like manual generator usage being astonishingly ugly:

while (true) {
    try {
        value = generator.next();
        ...
    } catch (e instanceof StopIteration) {
        break;
    }
}

vs.

while (generator.hasNext()) {
   value = generator.next();
   ...
}

If we're not too concerned about the syntax of using generators manually, then I'd just say make it a non-goal.  You can pass a generator around but you can only iterate using iteration syntax.  This would allow implementations to use whatever behaviour works most efficiently for them internally, without exposing it to developers.

The more I think about this, the more I like it.  Let's assume you can't directly call the iterator - for(of), comprehensions, etc work.

If it becomes sufficiently important to someone to make it "callable" then they can do:

Iterator.prototype.next = function() {
    for (value of this)
        return value;
    throw StopIterator; // Or return magic value, etc
}

> 
>> My personal concern with all of these is how they deal with nested iterators.
> I don't see the concern. Can you provide a use case/code sample where nested iterators would be a problem?


You know what?  I don't think I actually care.  I think I was swayed by a random blog post about how nested iterators suck :D - i was thinking of things like n-ary tree walkers and realised that most "solutions" end up being hideous crimes against code anyway :D

--Oliver




More information about the es-discuss mailing list