Question

Let's we say that we have following generator function:

var gen1 = function * (){
  yield 1;
};

And we have two more generators which yields above generator:

var gen2 = function * () {
    yield gen1;
};

var gen3 = function * () {
    yield *gen1;
};

Does someone known what is difference between yield gen1 yield *gen1. What does * do to generator?

Was it helpful?

Solution 2


QUOTE:

The yield* operator delegates to another generator. This provides a convenient mechanism for composing generators.

The expression yield* <<expr>> is equivalent to:

let (g = <<expr>>) {
    let received = void 0, send = true, result = void 0;
    try {
        while (true) {
            let next = send ? g.send(received) : g.throw(received);
            try {
                received = yield next;
                send = true;
            } catch (e) {
                received = e;
                send = false;
            }
        }
    } catch (e) {
        if (!isStopIteration(e))
            throw e;
        result = e.value;
    } finally {
        try { g.close(); } catch (ignored) { }
    }
    result
}

This is similar to a for-in loop over the generator, except that it propagates exceptions thrown via the outer generator’s throw method into the delegated generator.


Source: http://wiki.ecmascript.org/doku.php?id=harmony:generators#delegating_yield


I haven't taken much time to fully understand it, but yield* gen; seems similar to yield gen(); Correct me if I'm wrong (though I fully suspect there will be some corner cases, such as the context of any exceptions.)

OTHER TIPS

The effect of your code is like this:

for (let x of gen1()) console.log(x)  // "1"
for (let x of gen2()) console.log(x)  // "function* gen1() { yield 1; }"
for (let x of gen3()) console.log(x)  // throws TypeError

What you probably meant was:

var gen2 = function* () {
  yield gen1();
};

var gen3 = function* () {
  yield* gen1();
};

In that case you get:

for (let x of gen2()) console.log(x)  // "[object Object]"
for (let x of gen3()) console.log(x)  // "1"

That is, a plain yield just returns whatever the operand expression evaluates to (in the case of gen2, an unused iterator object). A yield* on the other hand delegates to another iterator. It will yield whatever that iterator yields, until it is exhausted. More concretely:

function* g() { yield 1; yield 2; yield 3 }
function* h() { yield 4; yield* g(); yield 5 }
function* i() { yield 6; yield* h(); yield 7 }

for (let x of i()) console.log(x)  // 6, 4, 1, 2, 3, 5, 7
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top