Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript Generators question - explain this code

I am reading "The JavaScript Handbook" by Flavio Scopes. He introduces the concept of Generators.

function* calculator(input) {
  var doubleThat = 2 * (yield(input / 2))
  var another = yield(doubleThat)
  return (input * doubleThat * another)
}

// He then runs the following code

const calc = calculator(10)
console.log(calc.next())

Output

{value: 5, done: false}

calc.next(7);

Output:

{value: 14, done: false}

I understand the first output, but I don't understand the second one. Why is the output 14?

My understanding is that the next time .next() is called on calc, it should continue on the line AFTER the one on which it last paused.

Well, that line is this one: var another = yield(doubleThat) and the value of the variable doubleThat at that point should be 10, so I'm expecting the second yield to return an object with a value of 10.

I don't think the example in the book is a good one, as I understand the concept of Generators (Python) and Iterators (C++/Python), and I understand other Javascript examples of Generators - but I simply do not understand what is going on here.

Can anyone explain why the value returned after calc.next(7) is 14?

like image 958
Homunculus Reticulli Avatar asked May 08 '19 12:05

Homunculus Reticulli


People also ask

What is JavaScript code generator?

A Javascript Code Generator is a tool that makes coding process faster. Zontroy provides such a generator. It produces code in a manner that it is like written by a developer. A javascript developer can generate tons of code using Zontroy Code Generator.

What is generator function example?

Syntax : // An example of generator function function* gen(){ yield 1; yield 2; ... ... } The Generator object is returned by a generating function and it conforms to both the iterable protocol and the iterator protocol.

Which is the correct syntax for a generator?

To create a generator, we need a special syntax construct: function* , so-called “generator function”. Generator functions behave differently from regular ones. When such function is called, it doesn't run its code. Instead it returns a special object, called “generator object”, to manage the execution.


2 Answers

The call to .next(7) provides a value for that first yield expression, overriding the value 5 that it previously computed and returned. It's a two-way relationship. The first yield "pauses" mid-expression, to be clear. Execution continues from inside that expression, not the next statement.

That said, I am inclined to agree that it's a questionable example, because I'm not sure that's a realistic situation. It's hard to imagine code like that constructed on purpose for some real application.

like image 72
Pointy Avatar answered Oct 03 '22 23:10

Pointy


function* calculator(input) {
  var doubleThat = 2 * (yield(input / 2))
  var another = yield(doubleThat)
  return (input * doubleThat * another)
}

const calc = calculator(10)
console.log(calc.next()); 

At that point you reach the first yield that is 10 / 2.

Then

calc.next(7);

the code is now this

var doubleThat = 2 * (7) // yield expression transformed into 7

Therefor the value is 14

You can gain some insight with the debugger

function* calculator(input) {
  var doubleThat = 2 * (yield(input / 2))
  var another = yield(doubleThat)
  return (input * doubleThat * another)
}

const calc = calculator(10)
debugger;
console.log(calc.next()); 
debugger;
console.log(calc.next(7))

The only weird thing is that when you enter the second next the debugger gets you on the second line of the function, seemingly not executing the 2*7. I think that's just seemingly because it doesn't stop mid expression but I could be wrong.

like image 38
Ced Avatar answered Oct 03 '22 22:10

Ced