Skip to content

Latest commit

 

History

History
159 lines (111 loc) · 3.9 KB

71.two-way-generator.md

File metadata and controls

159 lines (111 loc) · 3.9 KB

71. two-way generator

Problem

https://bigfrontend.dev/quiz/generator-2-way

Problem Description

What does the code snippet below output by console.log?

function* gen() {
  yield 2 * (yield 100);
}

const generator = gen();
console.log(generator.next().value);
console.log(generator.next(1).value);
console.log(generator.next(1).value);

Answer

function* gen() {
  yield 2 * (yield 100);
}

const generator = gen();
console.log(generator.next().value); // 100
console.log(generator.next(1).value); // 2
console.log(generator.next(1).value); // undefined

Explanation

On the first iteration (generator.next().value), the inner yield yield 100 is resolved, so the console logs 100.


On the second iteration (generator.next(1).value), generator.next(1) passes 1 to the outer yield, so it is yield 2 * 1 and logs 2. When providing an argument to .next(), the argument becomes the result of yield. For example, in variable = yield expression, the value passed to .next() will be assigned to the variable. However, the value passed to .next() will be only assigned when resuming execution from a previous yield, the argument passed to the first call to .next() will be ignored. In other words, what you're passing in to .next() is being returned from the previous yield.

Consider the following example:

function* gen() {
  const result = yield '2 + 2 = ?';

  console.log(result);
}

const generator = gen();

const question = generator.next().value;
console.log(question); // 2 + 2 = ?

generator.next(4); // 4
function* gen() {
  const result = yield '2 + 2 = ?';

  console.log(result);
}

const generator = gen();

const question = generator.next(1).value; // Argument `1` is ignored.
console.log(question); // 2 + 2 = ?

generator.next(4); // 4

If we don't provide any argument to the second .next(), it will logs undefined:

function* gen() {
  const result = yield '2 + 2 = ?';

  // yield result;
  console.log(result);
}

const generator = gen();

const question = generator.next().value;
console.log(question); // 2 + 2 = ?

// console.log(generator.next().value); // undefined
generator.next(); // undefined

So, we can rewrite the code snippet from the problem as following:

function* gen() {
  const returnedFromYield = yield 100;
  yield 2 * returnedFromYield;
}

const generator = gen();
console.log(generator.next().value); // 100
console.log(generator.next(1).value); // 2

The third generator.next(1).value returns undefined, because the end of the generator is reached.

function* gen() {
  yield 2 * (yield 100);
}

const generator = gen();
console.log(generator.next().value); // 100
console.log(generator.next(1).value); // 2
console.log(generator.next(1)); // { value: undefined, done: true }

If we have a return statement at the end of the generator function gen(), then the third .next() will return whatever the return statement returns:

function* gen() {
  yield 2 * (yield 100);
  return 'Final result';
}

const generator = gen();
console.log(generator.next().value); // 100
console.log(generator.next(1).value); // 2
console.log(generator.next(1)); // { value: 'Final result', done: true }

If we assign yield 2 * (yield 100) to a variable and pass an argument to the third .next(), then it will return the argument:

function* gen() {
  const returnedFromYield = yield 2 * (yield 100);
  return `Final result: ${returnedFromYield}`;
}

const generator = gen();
console.log(generator.next().value); // 100
console.log(generator.next(1).value); // 2
console.log(generator.next(4).value); // Final result: 4

Reference