Transcript from the "Challenge 7: Solution" Lesson
>> Kyle: Exercise 7, let's dig into the solution. I'll walk you through that, so, item one should have been pretty straight forward. We need to write two functions, call them whatever you want. I'm gonna call them but each one of them should return a specific number. So I'm gonna make my foo function return the value ten and I'll make my bar function return the value 42, just because those are my two favorite numbers.
[00:00:34] That's item one. Now item two said write an add function that takes two numbers. That's pretty straightforward, so function add takes an x and a y. Returns the addition of those. Item three says write an add2() function, I guess also to show how we can use that. Item 2 we wanna add by calling foo, and calling bar, and, of course, we know that would return the number 52.
[00:01:06] All right, now we wanna create the add2 function which takes two functions to call. It uses the add utility, so we basically want it to do the same thing. We want it to use the add utility, call fn1() and call fn2(). Pass those into the add utility.
>> Kyle: And to show how we would use that we would say add2 and we'd pass foo and bar as is rather than passing the execution of them.
[00:01:44] Again, both of those added together will return 52, that's items one through three. Let me pause there and see if anybody had any questions on items one through three.
>> Kyle: All right, now item four said we wanna go back and essentially replace that foo and bar With a utility that will make functions like that.
[00:02:09] So I'm gonna create a new function that will produce functions that return numbers. And you could have called this utility whatever you want, but there's a real name for this in functional programming. and I always get a smirk out of the name for it, because the name for this utility is constant.
[00:02:31] Even though it flies in the face of what we talked about with the Conskeyword [conskeyword/g] earlier in the course. The Constant, as the name of this utility, it takes a value, and it doesn't just return that value, it returns a function that will return the value So it's a machine making machine.
>> Kyle: Using that utility, we can now make the foo and the var, if we wanted to save var foo = constant(10) and var bar = to constant (42).
>> Kyle: So I'll take those and replace these two functions with that utility.
>> Kyle: So that's item four. Let me just, to save ourselves some space, do some combining onto single lines here.
[00:03:28] All right now using that we have the same call we can use that to call foo and bar, or we don't even really need the foo and bar created as separate variables. We can just simply call add2 with constant of ten and constant of 42.
>> Kyle: Item 5 is where things started to get a lot more interesting.
[00:04:01] Addn which should be able to take an array of two or more of such functions And only using the add 2 utility, figure out how to add them together. Now, we know that add 2 only takes two functions, so we're gonna need to do something to lift that add 2 function to a list of potentially three or more functions.
[00:04:25] So if we define a function add2, I'm sorry, addn (fns) that takes a list of functions, an array of functions, what strategy do we wanna use, or what's the algorithm that we wanna use here? Some of you may have said well, what I'm gonna do is I'm gonna loop through this list I'm gonna take two items as a time, pass them into the add2 utility which gives me the result.
[00:04:52] And then take that result, which is a number, and re-wrap it in a function using the constant. And then now that function plus another one, so basically you would Take two functions, reduce them down to a number. And then have to make it into another function and then reduce it and then make it into another function.
[00:05:11] And that churn of unlifting a value and then relifting it back, and unlifting it and relifting it back, that should feel a little bit unusual. That should feel a little bit awkward, when I run into those sorts of solutions. I take a step back and say, well if I'm already representing things at function, as functions.
[00:05:31] I don't want to go back to the non-function form and then after relift it, so what's a different algorithm that I could use? Because we know the add2 function will reduce it, will unlift it down to that numeric value We don't wanna call add2 yet. We don't want to call it into the last possible moment, does that make sense?
[00:05:53] Algorithmically that's the way my brain goes, I don't want to call it yet, so, we could introduce this idea of laziness. We could introduce the idea of instead of reducing two number producing functions down to a number. Instead what we could do is say the combination of those two functions could be a composition of those two with being called with add to.
[00:06:17] So we would be producing a bigger and bigger function, that is lazy. It defers all of those add2 cols until the last possible moment and given that my algorithm then could start with a four loop over the list. And take two items from the list. Make them into a single function that would pass that to add2 and then replace the two items in the list with that newly composed function.
[00:06:43] And then just keep doing that until I've left with basically just two functions and then call them. So let me code that with a for loop or actually not with a for loop but with a loop. So, the first thing I want to do is since I've being given an array I want to treat that as if an array that I can't mutate.
[00:07:01] So, I'm going to make a copy of it, because I actually want to mutate internally a functions list, so I'm going to make a copy of functions. And then essentially what I'm going to do is in my base condition, which we'll get to in a moment I'm going to assume that functions is down to two items.
[00:07:19] Its length is two now, if that is the case than all I need to do is call the add two utility and give it fn sub zero and fn sub one. That is my base condition. Now, before I get to that base condition, I wanna keep reducing my list if you will.
[00:07:40] I wanna keep composing the first two items of my list down until it gets to that, so, I'm gonna say while the fns.length is greater than 2
>> Kyle: While that array is greater than 2. Keep doing this thing. Now, what I'm going to use is a little bit, just to save on some typing, I'm going to use a little bit of ES 6 sugar to help some of these work a little bit cleaner.
[00:08:05] You might not have gone exactly this approach, but hopefully the algorithm is making sense. What I'm gonna do is use some block scoping and some destructuring, cuz I'm gonna have some closure here and block scope will help with that. By destructuring, what I'm gonna do is take that fns array, and destructure it down into three separate parts.
[00:08:24] I'm gonna create an fn0, an fn1, and then the rest of the fns and I'm gonna destructure that FN's array. So I now said that the item in the first position, I'm gonna FN0. The one in the second position, FN1 and everything else i'm gonna call rest. Call it whatever you wanna, but I call it rest, so that's essentially breaking down my list from one list into kind of like a head, which are these first 2 items and then my tail which is called rest.
[00:09:05] Now that I have those individual parts, I want to reconstruct my list So I'm gonna reassign the fns. I wanna reconstruct that list and at the end of the list, I wanna go ahead and include everything that was in rest. But in the first position of fns, I wanna create that function that wraps around my call to add2, so I'm gonna put a function here.
>> Kyle: And that function, when called, should call add2 with fn sub 0 and fn sub 1. So that call add2 hasn't happened, but I've made a function that will do it. And I made a function that will just keep doing that and keep doing that and keep doing that and keep doing that.
[00:09:53] So if you visualize in your head, we've got this big, big, giant, nested set of functions, it's a big internal pyramid of functions nested inside of functions. And at the very end of this foreloop, I'm left with fns[o] as my big harry nested function and fns is just the final function from the list left over.
[00:10:18] But those two function when you code them they will be both compute their own number and be passed into add 2.
>> Kyle: So, let's try this utility.
>> Kyle: And I'm gonna make up a list of some numbers here, numbers that I should be able to add together in my head.
[00:10:50] That should end up with the number 35 if I did my math correctly. Let's take that over to the browser and verify that I didn't make a mistake in my algorithm. I did make a mistake, where did I make a mistake.
>> Kyle: One moment, what you're passing is just constant values into the functions.
[00:11:31] You are correct [LAUGH] Sorry about that. Okay, these all need to be their function representatives [SOUND] let's try it again. [SOUND] Still didn't get on, is it cuz they're calling add2 instead of addn on line 24?
>> Kyle: No, add2 takes two functions which is what we want. I wanna pass those in, we're passing in two functions to it.
>> Speaker 2: On 24.
>> Speaker 3: Yeah, that should be added.
>> Kyle: Of course it is, I'm sorry.
>> Kyle: I've only done this exercise 100 times, how did I make that mistake. Sorry about that, thanks for the catch.
>> Kyle: There we go.