What is a generator?

Posted on Updated on

What is a generator?

What is a generator in JavaScript? Generators and Iterators seem to be linked, According to MDN, “The Generator object is returned by a generator function and it conforms to both the iterable protocol and the iterator protocol.” Still confused? You’re not the only one. Ok, let’s dig deeper into this.” Looking around, I see that Arfat on his blog wrote “A generator is a function that can stop midway and then continue from where it stopped. In short, a generator appears to be a function but it behaves like an iterator.” That seems to be starting to make more sense.

Looking at the generator from the perspective of an iterator that can pause and continue when needed, this could have many applications. A simple way of looking at it is that you allow yourself 5 Oreos a day. That’s cookies not packages! So if we had a generator “takeOreo” for Oreos, we could call “takeOreo”, and it would give back the cookie number we are on. Once we had our 5, if we called takeOreo again, it would be “done”. “A generator is a function that can stop midway and then continue from where it stopped.” So this appears like we made a pseudogenerator using Oreos and our diet.

How can we code the above pseudocode?  The syntax for a generator function is “function * name” not “function name” Looks like according to MDN, it’s just convention. “The function* declaration (function keyword followed by an asterisk) defines a generator function, which returns a Generator object.” Lets start coding. Lets start of naming the generator

function* giveOreo(){   
}

Now that we have a name, lets add the body. The thing is, when we call a generator function, its not going to start iterating immediately. Rather, we get back an iterator object. But how do we create that objecT? “ When the iterator’s next() method is called, the generator function’s body is executed until the first yield expression, which specifies the value to be returned from the iterator ” OK lets add this:

function* giveOreo(){
  let index=1; //start with 1, you cant get 0 cookies if you take a cookie
  while(index <= 5){
    yield `You eat cookie ${index++}`
  }
}


 

Ok how would we run it now that we have a function?

let todaysOreos = giveOreo()
console.log(todaysOreos.next().value) //You eat cookie 1
console.log(todaysOreos.next().value) //You eat cookie 2
console.log(todaysOreos.next().value) //You eat cookie 3
console.log(todaysOreos.next().value) //You eat cookie 4
console.log(todaysOreos.next().value) //You eat cookie 5

Great. We have a our 5 cookies. What about when we call it again?

console.log(todaysOreos.next().value) // nothing returned

So no more cookies. But can we force the generator to tell us that there are no more cookies? “ When a generator is finished, subsequent next calls will not execute any  of that generator’s code, they will just return an object of this form: {value: undefined, done: true}.” But to get the generator to be “done” we have to return something. Lets do that.

If we change the code, we can get back one last message then then the generator is done:

function* giveOreo(){
  let index=1; //start with 1, you cant get 0 cookies if you take a cookie
  while(index <= 5){
    yield `You eat cookie ${index++}`
  }
  return "No more cookies for you"
}

let todaysOreos = giveOreo()
console.log(todaysOreos.next().value) //You eat cookie 1
console.log(todaysOreos.next().value) //You eat cookie 2
console.log(todaysOreos.next().value) //You eat cookie 3
console.log(todaysOreos.next().value) //You eat cookie 4
console.log(todaysOreos.next().value) //You eat cookie 5
console.log(todaysOreos.next().value) // "No more cookies for you"
console.log(todaysOreos.next().value) // undefined

Now if we REALLY wanted to just keep getting messages instead of undefined we could do this: make a permanent message loop after the cookie loop is done This could be a little more useful than an undefined.

function* giveOreo(){
let index=1; //start with 1, you cant get 0 cookies if you take a cookie
  while(index <= 5){
    yield `You eat cookie ${index++}`
  }
  while(true){yield "No more cookies for you"}
}

let todaysOreos = giveOreo()
console.log(todaysOreos.next().value) //You eat cookie 1
console.log(todaysOreos.next().value) //You eat cookie 2
console.log(todaysOreos.next().value) //You eat cookie 3
console.log(todaysOreos.next().value) //You eat cookie 4
console.log(todaysOreos.next().value) //You eat cookie 5
console.log(todaysOreos.next().value) //"No more cookies for you"
console.log(todaysOreos.next().value) // No more cookies for you
console.log(todaysOreos.next().value) // No more cookies for you
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s