George Hawkins
George Hawkins

Reputation: 38784

Why are Javascript generators both iterators and iterables?

Why is it useful/necessary that a generator be both an iterable and an iterator?

I think of iterable and iterator as quite distinct, e.g. a collection is an iterable, this means I can ask for an iterator on it and each time I do so I get a new iterator that allows me to step through the complete collection once.

A generator appears to be most like an iterator, i.e. once you step through its elements once you can't do anything more with it, yet as well as implementing next() it implements the get-iterator logic of iterable but only such that this logic returns the generator itself:

$ node
> const genFn = function* () { yield *[1, 2, 3]; }
> const gen = genFn();
> gen.next();
{ value: 1, done: false }
> gen == gen[Symbol.iterator]();
true
> for (const val of gen) console.log(val);
2
3

Why is it necessary that a generator be an iterable in addition to being an iterator?

Upvotes: 6

Views: 310

Answers (1)

ShadowRanger
ShadowRanger

Reputation: 155418

Because it allows the interpreter machinery to unconditionally request a "new" iterator whenever it needs one, without worrying if the iterable is already an iterator. It's much easy to write code for implementing the for/of loop that unconditionally calls .iterator on everything it receives as part of the setup process, rather than making every initiation of iteration perform type checking to see if what it received was already an iterator or not, and only conditionally call .iterator.

Python uses the same iterator protocol; all iterators are iterables where their equivalent "getiterator" method is defined to be the identity function.

It makes sense logically too. "Iterable" means "able to be iterated" (which covers both iterators and things that can create iterators). The concept of an iterator is a superset of the concept of iterable things, so they need to provide the iterable interface.

Upvotes: 3

Related Questions