ES6 generators. Example where there is no yield expression for the first next ()
For ES6 generators, why the author of this blog post says:
from: http://davidwalsh.name/es6-generators
"First next (..) call, we are not sending anything. Why? Because there is no yield statement to get what we are passing."
Not your first call it.next()
(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 parameters (x in our example) using the iterator initialization foo (5), just like with regular functions.
First next (..) call, we do not send anything. What for? Because there is no yield expression to get what we are passing through.
source to share
The first one it.next()
matches yield(x + 1)
, which results in 6 as expected. 12 in the next call it.next(12)
sets the value of this first result to 12, so it is y
set to double, or 24, and the iterator results in a value (y / 3)
that is 8. The final call before it.next(13)
sets the value of the second output to 13, which is set to z
, and gets the value return
that is 5 + 24 + 13.
Of course this is a little confusing due to the syntax
z = yield(y / 3)
which somehow looks like one, assigns the value of what is associated with y / 3
- z
. This is not true. y / 3
is the value that is assigned as the value of the iterator, whereas the z
value passed by the call after is assigned to it.next()
something completely different! It might be a little helpful to omit the parentheses and write it like
var y = 2 * yield x + 1;
var z = yield y / 3;
meaning that yield
is an operator, not a function call.
Regarding the error you are talking about in the trace, for example, this is "Sent value to newborn generator". It makes sense when you think about it. The value sent as a parameter it.next()
becomes the value of the last output in the generator. On the first call it.next()
, there is not the most recent output in the generator , so nothing needs to be taken on the passed value, hence an error.
Don't confuse pass parameters with a generator ( x
in your case), which simply provides a way to set up or initialize a generator by passing parameters it.next()
that serve as the value of the most recent one yield
in the generator.
You might find it helpful to consider how you would write an equivalent manual generator (just to simply return the next value instead {value, done}
and throw 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