Home > Software engineering >  In what order is this generator running code at each call of next()?
In what order is this generator running code at each call of next()?

Time:11-15

function* bankAccount() {
  let balance = 0;
  while (balance >= 0) {
    balance  = yield balance;
  }
  return 'bankrupt! ';
}

let userAccount = bankAccount();

console.log(userAccount.next());
console.log(userAccount.next(10));
console.log(userAccount.next(-15));

...this code works - I've run it and after the third call of next(), it returns bankrupt - but why? Surely when next() is called the third time, the loop will check the balance (which will still be 10 at that point), and then add -15 to the balance, and yield out -5...leaving the next iteration to yield bankrupt.

But thats obviously not the case, the balance seems to be updated with the yield value before the loop checks the current balance, but if that line of code is running first, then why is the loop running at all? wouldn't it just be yielding out the updated balance instantly?...so, which code is being run when?

CodePudding user response:

Order of operations:

  1. let balance = 0;
  2. while (balance >= 0) { - balance is 0 here
  3. yield balance - yields 0
  4. balance = <value passed to next = 10> - balance is 10 after that
  5. while (balance >= 0) { - balance is 10
  6. yield balance - yields 10
  7. balance = <value passed to next = -5> - balance is -5 after that
  8. while (balance >= 0) { - balance is -5 so break
  9. return 'bankrupt! ';

function* bankAccount() {
  let balance = 0;
  while (balance >= 0) {
    balance  = yield balance;
    console.log('inside loop', balance)
  }
  console.log('after loop', balance)
  return 'bankrupt! ';
}

let userAccount = bankAccount();

userAccount.next();
userAccount.next(10);
userAccount.next(-15);

CodePudding user response:

Surely when next() is called the third time, the loop will check the balance (which will still be 10 at that point), and then add -15 to the balance, and yield out -5.

This is nearly all correct. The biggest problem with it is that (as @Bergi correctly points out in the comments), the adding of -15 happens before the check. Therefore the conclusion:

and yield out -5

is wrong.

When -15 is added to the balance, which happens on this line when you called next with the -15 argument:

balance  = yield balance;

balance becomes -5, as you so rightly observe. So the next statement execute is the loop check itself. balance >= 0 is no longer true, so it doesn't loop again, and moves on to the final "bankrupt" yield - exactly as you've observed.

Perhaps your confusion is over how the next calls and yields line up. So here's a quick summary:

  • the first .next() call advanced the code to the first balance = yield balance;, where balance is 0. That's what's yielded, and the code awaits your next call to see what's added to balance.
  • then you call .next(10), so 10 gets added to balance. It reaches that line again, so 10 is yielded, and again the generator waits to see what you give it next.
  • then you call .next(-15), which yields the 10 value. As observed above, the next yield is outside the loop because balance is now -5 and the loop therefore does not continue

CodePudding user response:

It is about how yield works, you can read in depth here.

In your example the yield keyword causes the function generator to stop before the balance is increased, the following .next() call will increase the value, so in reality the loop goes as follows:

1st call -> balance is 0 as defined, we enter the while loop, but stop before the balance increase by yielding the current balance value

2nd call -> the yield expression results in 10, the balance is increased to 10, only now the first iteration is complete, we enter the loop again, but stop before balance increase by yielding the current balance value

3rd call -> the yield expression results in -15, the balance becomes -5, the while condition is not valid anymore

  • Related