x = [0, 1, 2, 3, 4, 5, …]
The value of x as seen from other cells would not be the array; it’d first be 0, then 1, then 2, sixty times a second. It would be as if there were an implicit yield-star:
x = yield* [0, 1, 2, 3, 4, 5, …]
Generators are less common that iterables, so it was convenient to limit the special interpretation to this more specific type. Also, you can easily adapt any iterable to a generator through yield-star, providing an opt-in interpretation if desired.
Also, like an iterator but not necessarily an iterable, reading a generator is inherently destructive (read-once). Multiple cells reading directly from a single generator using generator.next would be non-deterministic, and you generally want to avoid side-effects in Observable. Making generator the representation of a value over time affords more deterministic behavior.
Note that reading an iterator is also destructive, and even an iterable is sometimes: many iterators implement iterable (the [Symbol.iterator] method) by returning itself! For example, a Map can be iterated many times, but the return value of map.values can only be iterated once; you have to call map.values each time you want to iterate. But the common types are pure, and you can always splat a destructive iterable like map.values into an array using the spread operator:
To answer the other question, generator.return allows generators (and generator cells) to clean up after themselves. You can read about that here:
Also, in case anyone reading hasn’t seen it yet, here is the introduction to generators: