michjo
michjo

Reputation: 417

Understanding how the yield impacts the return value in a JS generator

Let's say I have some function as follows:

function *hello(x) { // define generator
  while (x < 7) {
	console.log(`before: ${x}`)
    x += yield x + 1; // generator object will have value x + 1, then next step of generator has value x + x and not x + x + 1
	console.log(`after: ${x}`)
  }
  return x; 
}
var world = hello(3);
console.log( world.next(2) ); 
console.log( world.next(2) ); 
console.log( world.next(2) );
console.log( world.next(2) );

// before: 3
// {value: 4, done: false}
// after: 5
// before: 5
// {value: 6, done: false}
// after: 7
// {value: 7, done: true}
// {value: undefined, done: true}

I can see that the line with the yield returns a generator object with a value of x + 1, but the actual value of x is only increased by x, not x+1, as can be seen by the values in the before and after console logs. Why is it that the value of x, which comes to the right hand side of the yield is added to the current value of x, but the + 1 is not? I know that the value of x is what is being added, because if I change the value passed to the generator object in the next function, the before and after values reflect how much x was incremented by.

function *hello(x) { // define generator
  while (x < 7) {
	console.log(`before: ${x}`)
    x += yield x + 1; // generator object will have value x + 1, then next step of generator has value x + x and not x + x + 1
	console.log(`after: ${x}`)
  }
  return x; 
}
var world = hello(3);
console.log( world.next(1) ); 
console.log( world.next(1) ); 
console.log( world.next(1) );
console.log( world.next(1) );

// before: 3
// {value: 4, done: false}
// after: 4
// before: 4
// {value: 5, done: false}
// after: 5
// before: 5
// {value: 6, done: false}
// after: 6
// before: 6
// {value: 7, done: false}
// after: 7
// {value: 7, done: true}
// {value: undefined, done: true}

Upvotes: 3

Views: 132

Answers (1)

Mark
Mark

Reputation: 92481

The value of the expression:

x += yield x + 1;

is not x + 1. The value x + 1 is what is yielded to the caller. The value of yield in the generator is whatever was passed in. In this case, it's always 1 because that's what is being passed to it with:

world.next(1)

A generator stops as soon as it hits the yield so in this case

x += yield x + 1;

You can think of it as working like:

yield x + 1; // pass this value to the called

[Pause]

[Next call from  world.next(1)]

x = 1 // value passed in from caller

Upvotes: 3

Related Questions