6

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?

3
  • Because you can use a generator in any context where you can use an iterable…!? Commented Mar 8, 2018 at 10:38
  • OK - then the flip is to ask "well if it's an iterable why is it necessary that it also be an iterator?" Collections are iterables without also being iterators so I'm just asking why its necessary that generators be both? Commented Mar 8, 2018 at 10:52
  • Because an iterator specifically can only be iterated once, which is a critical distinction. Commented Mar 8, 2018 at 10:57

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

2 Comments

OK - it looks like I confused by the following remark in a tutorial "Generator objects conform to both the iterable protocol and the iterator protocol." This made me think this must be something unusual and worth pointing out, whereas it should have been enough to say "generator objects are iterators" (which automatically implies that they are also iterables, this being true of all iterators and not some special characteristic of generators). I'm coming from Java where the Iterable interface does not extend the Iterator interface, the two are distinct.
OK - after a bit more experimentation it seems that the iterators of Javascript collections are also iterables but this is just for general convenience, it isn't the case that all iterators are necessarily also iterables. I.e. not all iterators implement [Symbol.iterator]() in addition to next().

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.