This course has been updated! We now recommend you take the TypeScript Fundamentals, v3 course.
Transcript from the "Iterators" Lesson
>> Mike North: So I'm gonna show you this, which is the next level. We have the ability because next is a function, functions take arguments, we can push things into the iterator. So the ability to pass values in is important. And has anyone here used RX before, RXJS and observables?
[00:00:22] So it's the idea of being able to push things in and get things out. This two-way communication provides the foundation for a lot of cool reactive programming patterns. And the way we have to think of this is, in this situation we have. Sorry, I need my Presenter view to talk through animations.
>> Mike North: So in this situation we pull an iterator off of this generator function and as we know, nothing happens, right. We have not even begin to execute the lines of code inside this generator function. That doesn't happen until we ask the iterator for its first value. That this is the same as when we had that break point on the first line of that generator function and we invoked the generator function.
[00:01:10] It returned its iterator, but we did not stop at that break point. The game has not started yet, just think of this as a wrapper around that code. And when we call next, that generator function is gonna start executing code until we hit a point where we yield out a value.
>> Mike North: So in this case we're gonna call next and what's gonna happen is we're going to emit 5. So and the reason is we've got last result as 0. And then think of what's happening here. This is the first line inside the block following the while, right. Last result equals yield last result plus 5.
[00:01:50] So think of it as we're still on the right hand side of that assignment operation. And I told you when we pause execution, imagine as if we're pausing immediately to the left of the y in yield, we're pausing right there. We're sort of caught in the middle of that assignment operation.
>> Mike North: And so that is how we're going to get this 5 out. So think of it as the yield sucks in the value to its right and you're pausing right at the yield.
>> Mike North: So then we're still paused, what we're gonna do is pass the number 35 in to the next function.
[00:02:32] And think of yield as almost like a portal where we can push something in to that next function and it's gonna pop-out out of the left side of the yield. So when we take 35 and we push it in to the next function. That 35 is gonna be, that value is gonna finish the assignment operation we paused in the middle of.
[00:02:59] And so now last result is gonna be 35. So when I talk about it like a portal imagine it like whatever we put into next is gonna come out of the left side of yield.
>> Mike North: And so that'll be the new value of this variable.
>> Mike North: And then we're going to.
>> Mike North: Print out last result as 35 because, as we saw, we're gonna basically finish the assignment operation, log the next line out. Turn around, go through the y loop again, and then log out 35+5 is 40, and now we're paused at the yield again. And so now we're gonna put 100 in and so that's what we're feeding into last result.
[00:03:49] And then when we run this, when we hit play, what's gonna happen?
>> Mike North: What's the next thing that's popping up on the bottom right corner?
>> Speaker 2: Last result equals 100.
>> Mike North: Last result equals 100 and the new result is?
>> Speaker 2: 105.
>> Mike North: 105.
>> Mike North: It's a very, very new concept, but this starts to get really, really, really powerful later on.
>> Mike North: Any questions about this? I mean, I had tons of questions about this. If your question is, why on earth would I need to do things this way, I’m getting there.
>> Speaker 3: Is the generator stuff supported by a dabble polyfill or, yeah, how? It is, okay.
>> Mike North: So the polyfill that is most popular.
[00:04:41] Well, first let me say TypeScript has its own polyfill, TypeScript has its own support for generator functions. Babel brings in a Facebook library that is called Regenerator. Regenerator is the polyfill of choice for this. Do you wanna see what it looks like when we transpile a code?
>> Speaker 3: Not really, [LAUGH] I'm assuming it's really difficult to read.
>> Mike North: Keep in mind the search maps work pretty well so don't panic.
>> Mike North: Okay.
>> Mike North: We'll just do our simple one, let my grab the front end masters snippet that we just made. So think of it like a closure wrapped around a case switch where, essentially, we keep re-entering the same.
>> Mike North: Switch statement, but at a different case and that represents different pieces of code between yields.
>> Speaker 4: So when Babel does its work, it's hard coding every possible case for the sequence. I mean, it's literally-
>> Mike North: Only because this is a very literal generator function. What if I did this?
>> Mike North: Oop, that's gonna throw, now I've frozen that.
>> Group: [LAUGH]
>> Mike North: This is why, no, no. So this is why having a direct fill is sometimes dangerous here. Okay, I don't, do not finish that URL for me. Whew, it's just storing that in local storage here. So if we've got, let x equals one while false [LAUGH].
>> Mike North: Yield x++. So we'll agree that this x is changing, this is not every possible value.
>> Mike North: So what I just want you to see here is, let's see, so we begin in case 0 with x is defined by 1, and then we fall into case 1. So this would be, basically, case 0 is the entering case.
[00:07:20] That makes sense, right? And then we fall into case 1.
>> Mike North: This is our general situation for how y loops are transfiled in generator functions. So this would be the condition where true is false, think of it that way. It doesn't make sense right now because true is never false, but imagine that this were a dynamic value.
[00:07:47] This is, basically, saying if in this situation that the condition is no longer met we're done. So here is the other one that we're interested in we're returning x++, right. And the next context is 4, that, basically, sends us back into 1, and then x++, and the next context is 4.
[00:08:09] And so the next time we call the iterator we'll enter here and then we go back up here. So we're basically going from 4 to 1, 4 to 1, 4 to 1 and this is the way it looks like to have this sequence of infinite length. If this all looks like tough to understand code on the right side, don't worry about it.
[00:08:33] But I just want you to understand there's reason to this and that this is a pretty ingenious way to do it.
>> Speaker 6: Its actually really clever.
>> Mike North: It's super clever. It is ridiculously clever. So and source maps make it so that you're still stepping through, you, basically, can do something called black box the script, right.
[00:08:56] You can black box the Babel polyfill and you'll end up just stepping through your generator function as we were in the prompt snippet which is fantastic.
>> Speaker 4: One quick question in chat, so it does not store the previous next values? So the final one would be 145?
>> Mike North: The final one would be 140-
>> Speaker 4: The final.
>> Mike North: There's no final value in this situation.
>> Speaker 4: All right.
>> Speaker 4: Yeah, you might have already covered it so.
>> Mike North: So it does not start, that's four minutes ago, so maybe it was. Okay, so I think we were looking at this, there we go.
>> Mike North: So, let's see, it does not store the previous next value so the final value would be 145.
[00:09:51] We could keep, because we have a while true here, a yield inside a while true. There's nothing here, Rob, that would make this sequence stop, there's no final value here. One thing that is interesting though, as soon as we stop providing things to next we're gonna end up with some unpredictable results.
>> Group: [LAUGH]
>> Mike North: I'm taking bets.
>> Speaker 2: Five.
>> Mike North: Five? Yeah, so things we would have to consider now we absolutely need to pass the value in. Good news is, we can define an iterator that looks like that, right. With TypeScript we can say, when you call next give me something.
[00:11:01] And now we could get a compiler error if for that specific type of iterator we fail to give it what it needs. So, hopefully, that answers your question, Rob. There is no final value here and we know that because we, basically, have a single yield that is inside an infinite loop.
[00:11:19] Where we'll just, as often as you call next, we will get whatever we're gonna get.
>> Mike North: Okay.
>> Mike North: My fancy animations, we get a rerun.
>> Mike North: Okay, so we can define our own iterable. Sorry, there we go.
>> Mike North: And now because a generator function returns an iterator. Before we had to do some backflips, right.
[00:11:57] Before our defining, our own iterable looked like this.
>> Mike North: Where we had to say, we're returning an object that has a next function on it. We actually had to really explicitly define what our iterator looks like. When we go back to our generator function case because the generator function, the value it returns is an iterable, this looks much cleaner now.
[00:12:26] This is much more reasonable, where we can yield things one by one. We yield M, I, K, E if we use the for, of loop and we get this.
>> Mike North: So now, like I told you, we were going in the weeds, things look way more difficult than they need be.
[00:12:43] But now we're starting to see, hey, this is the way it's meant to be done. This makes a lot more sense, this is code that's not tangled up spaghetti.
>> Mike North: And let's say that we were trying to yield something that is in and of itself, iterable, right. I told you arrays, we can already pull an iterator off of an array, we demonstrated that.
[00:13:09] Strings are like arrays in many ways, right. We can use bracket notation to get an individual character out of a string. They have a length. So we can use this syntax yield* and, basically, you're saying when you say yield* you're gonna get the same result as we did before.
[00:13:28] In the essence we're saying, I'm going to give you an iterable and yield this iterable out one by one by one.
>> Mike North: So if we were to make this a little more meaningful, imagine we had a sequence like this. Where we have a couple things that are iterable in and of themselves and we're sort of stitching together a few different sequences.
[00:13:56] In this case we're gonna just see 1, 2, 3, 4, 5, 6. Because we're saying first, I've got this array, one by one yield these values out. And then here's a single value, yield that out. And then finish with these things here.
>> Mike North: This is super cool stuff, I get really excited talking about this.
>> Mike North: This opens up new possibilities for a clean easy to understand implementations of things that previously were really, really hard and really messy.