Kyle walks through the solution to exercise 1.
- We said in the slides, before I intro'ed the exercise, we said in the slides portion, that one of the ways to turn a stateful program, a side-effect program, into a pure program, is to pass in the entire universe of state. Now, there's lots of different ways of doing that, you can pass it in as an object, of course. Here we're just being very simple to illustrate the concept. There's a couple of variables that represent the state. So what are those variables that represent the state? And let's look closely. Does x represent the state of our program? Not really.
X is a parameter to the universe, but it's not really part of the state. So we don't necessarily need to represent x in some stateful fashion. Although, we're going to need x. So it's going to need to be one of our arguments. Well, what about y? Y, clearly, is something that changes over time, it's incremented there on line 2. Something that changes over time, it is part of our state. So we're going to need to pass in that initialization of that state. Initializing it of course to five, like we do on line 6. So, y is part of our state. And z, is z part of our universe? Does z change over time? Well, z is an output of our program, but it's not something that is reused each time.
It's reset, and we just assign it on line 3, and it doesn't matter whatever value it previously had. So, z is not actually something we need to import as part of the state of our universe, it's just something that's going to represent an output. Okay? So, all of that notion is just to help you with the concept of syntactic things are going to look very much different from what we already do. So, let's use a bar. And I use, by the way, these functions, foo, bar sorts of things, because if I gave you too heavy of something that was kind of a specific problem domain, then it starts to get a little bit like your brain has to not only wrap your head around these concepts, but your brain also has to wrap your head around that particular problem domain, and if it's one you're familiar with, great.
If not, well now you have two things to learn. And I want you to have as few things to learn as possible. So that's why I use the foo and the bar thing. But, we will, to whatever extent possible, try to make these things a little bit more concrete as we go along. Alright, so, one thing I'm going to do, and this is just a complete pure side note, but I have taken, recently in my programming, to inverting the way, I normally used to write the functions at the top, and the executable code at the bottom, of any particular scope, any particular file, or any particular function. And I now do the reverse.
And the reason I do that is because it's much easier, I found this maintenance-wise, to be much easier to open up a file or to look at a function, and at the very top, be able to see everything that it's doing. And then I rely upon function declarations and the fact that function declarations are hoisted to, that they'll be definable here. So I can call foo before it's technically been declared because the java script's compiled, and it's going to take care of that with, the short-hand way of talking about that is hoisting. I talk more about that in the books and in the advanced training video if you're more interested in that.
But I'm going to move the function to the bottom just because I'm trying to practice that more as a discipline for myself. I find that to make code a little bit easier to understand. So, y isn't going to be a variable, like a local variable. It's going to be something that's passed in, for sure. And, in fact, we're also going to pass in x, because we need that x value to be used. So I'm not going to declare y or x as variables, but I do need a z, because I'm going to need to be able to return to z.
So, the foo function, as we know it, takes an x. Now, I don't have to pass the x in. I could take the x out, and just simply reference it. You'll notice there, that on line 8 I have an x, and I can reference that. That's going to be called closure. But we're not getting to the closure point yet, so I'm going to formally pass in the x. And that means the x needs to be passed in here. Whatever the x was given to my universe, I'm going to pass that in to this inner interior function. Now, you notice that I'm changing a y, that of course is changing it as a result of that, that lexical scope, that closure over the y.
And also the z, it's changing the z. So I'm going to call the function foo. And then I know that my y and my z have been set to their proper values for the end of my program. So what do I need to do? Just simply return them. And I'm going to encapsulate them in something, and a functional programmer usually turns to an array when they want to encapsulate some value. Lists are particularly convenient, and we'll get more to lists later. So, I'm just going to simply return my y and my z. Now, you notice I'm not returning x. I could. But x isn't something that's changing as a result of any of what we're doing.
It's just simply an input to my universe. It's a starting state, it's an initial state, so I don't really need to return it. So I really only need to return that which changed, that which would be something that somebody wanted to observe. Now, if somebody didn't care about observing y, for example, of course this program changes y, so you probably do. But if you didn't care about changing y, you wouldn't even want to return that. You would only want to return that which somebody would want to observe. Okay, so that's our bar function. And it's going to execute the foo function, and then return the results of whatever those values are.
Clearly, on the inside, this function is as impure as it gets. Okay? Hopefully everybody can agree with that. But from the outside perspective, now, bar takes in a universe, and it returns back a result. And nothing on the outside of bar changes as a result of calling bar, which means we can call bar over and over and over again with the same inputs, and get the same outputs. That's how we've made it pure. So, just to illustrate that, instead of calling these foo variables down here, I'm going to call bar. I'm going to pass in an x, which in this case was the 20.
And I'm going to pass in a y, you remember, I've taken it out now, but remember our initial value state that we cared about with y was five. So if I pass in the value 20, and ask for the value 5 back. What am I getting? Well, let's run through it just to make sure, and then we can, you can of course execute this in the console of your browser if you care, but if I pass in 20 as x, 20's going to come in as x. If I pass in five as y, five is going to become six, and then I'm going to say six times 20, which is 120, and that's going to be my z.
So what am I expecting back as my return value? I'm expecting back an array with six, and 120. And if you try it, you'll notice that you get that value back. Okay? Now, if I called bar(20, 5) again, I'm going to get the exact same state back because now I'm dealing with a pure function. There are no side effects. It's a pure function. Okay? And of course if I called bar with 25, and I call it with six now, because six was my new state that I'm observing from y.
If I take that state, and I pump that back in as the starting point for my second run of this universe, now six is going to become seven, seven times 25, we're going to get, y is going to be what now? - [Student] Seven. - Seven. And we're going to get 125 back, okay?
This course was created by Frontend Masters. It was originally released on 03/08/2016. We're pleased to host this training in our library.
- Pure functions
- Manual composition
- Composition utility
- List operations