9

Let's say I've created an ES6 generator

function *createFibonacciIterator(a = 0, b = 1) {
  yield b;
  yield *createFib(b, b + a); // <== QUESTION IS ABOUT THIS LINE
}

Then I use that generator to get the first 20 results

let fibber = createFibonacciIterator();
for (let ii = 0; ii < 20; ii++) {
    console.log(fibber.next());
}

If I leave the * out of the yield *createFib(b, b + a); line things break, which makes sense because I don't want yield an iterator but an actual value.

What's the technical meaning of * in the generator?

Anthony Astige
  • 1,791
  • 9
  • 17

2 Answers2

2

For most cases

yield *smth;

makes the same thing as

for (let x of smth) {
  yield x;
}
Qwertiy
  • 14,618
  • 9
  • 41
  • 96
  • 2
    This is an OK simplification, but it fails to address what the `yield *generator()` evaluates to, which as it turns out is the end-of-iteration value `return`'ed by the generator object. It also does not correctly represent what happens when the consumer of the generator throws into the generator, etc. –  May 15 '16 at 17:24
  • 1
    @torazaburo, could you show an example? – Qwertiy May 15 '16 at 18:37
2

When the * is used in the function declaration this mean that it is a generator function.

But when it is used as yield *myGeneratorFunction(), the definition of the Ecmascript 262 specification, Section 14.4.14, says that the engine tries to resolve the generator function calling the next() method of iterator returned by the generator function.

When the yield is used without the * (for example, yield createFibonacci()), it returns the value of the expression after the yield. In the example is the value returned of the createFibonacci.

Henrique Limas
  • 287
  • 1
  • 10
  • Online spec: http://www.ecma-international.org/ecma-262/6.0/#sec-14.4.14 – Oriol May 15 '16 at 15:19
  • Yes, this is better. Thanks – Henrique Limas May 15 '16 at 15:42
  • 1
    This is a bit confused. You say *the next value of the iterator is the returned value of the function*, but `yield` is not a function. It's a keyword, which results in a value. You say "the engine tries to resolve...", but in fact what happens is `myGeneratorFunction` is called as expected, returning an iterable, and `yield *` operates on that as it would any other iterable (such as `[1, 2]`, for example). The generator function has no `next()` method; it is the iterable **returned** by the generator function that has a `next()` function. –  May 15 '16 at 17:13
  • The function that I mention was the createFibonacci and not the yield keyworld. And Yes, it is the iterable returned by the generator that it is going to be resolved. I'll edit to be clear, but it is correct what you say. Thanks. – Henrique Limas May 15 '16 at 19:36
  • 1
    Another way of saying what `yield *myGeneratorFunction()` does: it basically runs an generator within your generator (it "delegates" to another generator). For example, if you wanted to combine two iterators into one, you could do: `yield *genFunction1(); yield *genFunction2()`. Documentation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/yield* – Alexander Taylor Sep 01 '17 at 10:37