Search code examples
javascriptecmascript-6functional-programminggeneratorspread-syntax

When using spread syntax on a generator why return value is not retrieved


I was expecting 4 to be part of the sequence array, so why is it skipped?

function* generate() {
  yield 1;
  yield 2;
  yield 3;
  return 4
}
let sequence = [...generate()];
console.log(sequence); // 1, 2, 3


Solution

  • The return value of a generator function is not considered part of the sequence. It is returned from the last .next() call as {done: true, value:…}, where done: true implies that the sequence was completed and .next() should not be called again.

    Why is that so, why couldn't we just yield the last value with the done flag set to true? Because then we could not represent an empty sequence with an iterator - the first .next() call would already lead to at least one value.1

    So usually, generator functions do not return anything (but undefined), and all sequence values are yielded with the same syntax - there is no weird special syntax for the last value2:

    function* generate() {
      yield 1;
      yield 2;
      yield 3;
      yield 4;
    }
    

    1: Other languages do this differently. There, iterators have a separate .hasNext() method that is called before .next(), or their .next() method either returns a value or throws a StopIteration exception. They don't have any "final value".
    2: Having to know beforehand that a value is that last and using return instead of yield for it would make the logic for dynamically generated sequences much more complicated.