Transcript from the "Lazy vs Eager Execution" Lesson
>> Kyle Simpson: On this topic of closure, we need to understand the idea of deferring when things are occurring. It may not have been obvious from the code that we've looked at so far, from exercise or whatever. I wanna be very clear about this idea of lazy versus eager, cuz this is not very obvious until you dig into it.
[00:00:19] But it turns out to be a really powerful technique in your code. Let's take this function repeater, it takes in an input value called count, so if I call repeater of 10, then count is value 10. And it gives me back a function that is closed over that variable count.
[00:00:41] So if I'm closed over count, line 3, I'm closed over the count from line 1. And I return back that function, on line 7, I have a function called A. It's remembering the count variable in its internal stack, as was just being asked. And on line 9 when I call it, it uses that information to print me out a string of 10 As.
[00:01:09] And then I call it again and I get another string of 10 As, everybody with me? It's able to remember that count as many times as it's called, as long as A doesn't go away. A is gonna continue to remember the initial value that was passed in for count, which was the value 10.
[00:01:28] Matter of fact I could have called this variable A10, to make it more explicit. It's a repeater that is gonna do things 10 times. But I want to ask you this question, and this is how we're gonna dig into this idea of lazy, versus eager. On which line of this program, is it line 7 or is it line 9, when the actual work of constructing that string, occurs?
>> Kyle Simpson: Is it on line 7 when I make the string AAAAAA or is it on line 9 when I make the string AAAAAA?
>> Speaker 2: 9.
>> Speaker 3: 9.
>> Speaker 4: 9.
>> Kyle Simpson: Line 9, and then what about line 10, do I do the work again? Yeah, as a matter of fact, if that was really expensive work, like if I was looping over a million numbers and calculate.
[00:02:21] If that was really expensive work, I'd do it every single time the function was called, right? But what's interesting here is that I have essentially deferred the work. By doing the work on line 3 instead of on line one and a half. I have made it happen on line 9 instead of line 7 where I located the work determined when it happened.
[00:02:44] That's what we call lazy, or deferred. We're deferring that work by putting it into a function and deferring it until that function gets called. And you can do multiple layers, you could wrap a function inside of a function inside of a function. And then there's got to be three successive function calls there before the work actually happens.
[00:03:02] That's deferring or lazy for that work. Why might we want to defer the work? Again, this is very trivial, padStart kind of stuff, but what if this was computationally expensive work? Why might we want to defer computationally expensive work? One reason might be, if we weren't sure that in all conditions the function was ever gonna be called.
[00:03:28] What if the A function only get called in 10% of the cases? 90% of the time it never gets called. If we did the work upfront, 90% of the time we'd be wasting work, wouldn't we? By putting it in into this extra layer of function wrapping, we have deferred this work.
[00:03:46] So that the work will only happen in the 10% of the case, and not in the other 90%. Do you follow me? So that is a way to defer the work, what's the downside of deferring the work?
>> Speaker 5: It happens every time [INAUDIBLE].
>> Kyle Simpson: Now we're doing it every single time, so it would be a good idea to do deferral if we weren't sure if it was ever gonna be called.
[00:04:11] But it's maybe not such a great idea to do a deferral if we thought it might be call multiple times whenever it was called. Cuz then we would be wasting that work 5, 10, 100,000 times, right? So that's the deferral side of it, now, if that's a lazy way of doing it, what would be the opposite?
[00:04:28] What would be the eager way of doing it? Well, that would it be to move the work up to line one and a half, right, let's do that. Let's move the work to line one and a half. We still have the exact same outcome, which is line 10 gives us AAAAA, line 11 gives us AAAAA.
[00:04:45] But now let me ask you the question, when does the work occur, does it occur on line 8, or does it occur on line 10?
>> Speaker 6: 8.
>> Kyle Simpson: Now it occurs on line 8 it's eager, what's the benefit of doing an eager?
>> Speaker 7: It's done once.
>> Kyle Simpson: We only do it once, and if we call A 5,000 times, we only did the work once.
[00:05:07] It's good because we don't need to do the work unnecessarily. If we're gonna get the same answer every time, why do all the work over and over again, all right? So that's good, if we know it's gonna be called a bunch of times, do it once, cache it basically, right?
[00:05:18] Just cache it, and have it ready to go, that's what we're doing. What's the downside of doing it eagerly?
>> Kyle Simpson: What if A never gets called? Then we did the work unnecessarily. So you see the trade-off between the two? Sometimes lazy might be more preferred, sometimes eager might be more preferred.
[00:05:38] Both of these, by the way, are able to be done because we have closure. We are, in both cases, closing over something. In the previous slide we were closing over count, what variable are we closing over in this code?
>> Kyle Simpson: String, this str variable from line 2, that's the variable that we're closing on.
[00:05:58] So in both cases, closure enables, it's a choice of where we put the code. To decide whether we wanted to happen eagerly now, or lazily later.