ES6 Generators- Example where there is no yield expression for the first next()

半腔热情 提交于 2019-12-19 03:59:39

问题


For ES6 generators, why does the author of this blog post say:

from: http://davidwalsh.name/es6-generators

"The first next(..) call, we don't send in anything. Why? Because there's no yield expression to receive what we pass in."

Doesn't the first it.next() call (yield (x + 1))?

function *foo(x) {
    var y = 2 * (yield (x + 1));
    var z = yield (y / 3);
    return (x + y + z);
}

var it = foo( 5 );

// note: not sending anything into `next()` here
console.log( it.next() );       // { value:6, done:false }
console.log( it.next( 12 ) );   // { value:8, done:false }
console.log( it.next( 13 ) );   // { value:42, done:true }

You can see that we can still pass in parameters (x in our example) with the initial foo( 5 ) iterator-instantiation call, just like with normal functions.

The first next(..) call, we don't send in anything. Why? Because there's no yield expression to receive what we pass in.


回答1:


The first it.next() corresponds to the yield(x + 1), which results in 6 as expected. The 12 in the next call to it.next(12) sets the value of that first yield to 12, so y is set to double that, or 24 and the iterator results in the value (y / 3), which is 8. The final call to it.next(13) sets the value of the second yield to 13, which is set to z, and receives the value of the return, which is 5 + 24 + 13.

Granted, it is a little bit confusing, due to the syntax

z = yield(y / 3)

which somehow looks like one is assigning the value of something to do with y / 3 to z. That's not the case. y / 3 is the value being yielded to serve as the value of the iterator, whereas z is being assigned to the value passed in by the following it.next() call, something entirely different! It may be slightly helpful to omit the parentheses and write this as

var y = 2 * yield x + 1;
var z = yield y / 3;

keeping in mind that yield is a statement, not a function call.

As for the error you mention, in traceur for example it is "Sent value to newborn generator". It makes sense when you think about it. The value send as a parameter to it.next() becomes the value of the most recent yield in the generator. On the first call to it.next(), there is no most recent yield in the generator, so there's nothing to take on the value being passed, hence the error.

Don't confuse passing parameters to the generator (x in your case), which merely provides a way to configure or initialize the generator, with passing parameters to it.next(), which serve as the value of the most recent yield in the generator.

It may be helpful to consider how you would write the equivalent hand-rolled generator (simplified to just return the next value instead of {value, done}, and throwing when the generator is out of gas):

function foo(x) {
    var y, z, step = 0;
    return function next(val) {
        switch (step++) {
            case 0:               return x + 1;      break;
            case 1: y = 2 * val;  return y / 3;      break;
            case 2: z = val;      return x + y + z;  break;
            default: throw "generator finished";
        }
    };
}

Then:

iterator = foo(5);
iterator();             // 6
iterator(12);           // 8
iterator(13);           // 42


来源:https://stackoverflow.com/questions/26695346/es6-generators-example-where-there-is-no-yield-expression-for-the-first-next

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!