Transcript from the "Advanced Point Free" Lesson
>> Kyle Simpson: There are certainly more advanced techniques. And I wanna give you just a couple, this is just a quick glimpse at a couple of these. And we're gonna come back to them later in both lecture and exercise, okay? So if I defined a couple of utilities, and by the way, I'm not inventing these, these are ones that you would find in a functional programming library.
[00:00:20] But let's define one called mod, it's going to do modulus operation. It's doing something which might seem a little bit strange to you. I'm taking the first input mod on line 1, and taking y. And then I'm returning a new function called for x. In other words, that function's purpose is to receive the x input.
[00:00:43] That's why I called it for x, okay? And when that has been provided, when we have provided a y first and then an x, those are two separate function calls where we provide two inputs one at a time. Then what happens, is it does x mod y. So, we're providing them in a reverse order.
[00:01:03] That's gonna feel a little strange to you, but I'll show you in just a moment why we're gonna do that. And then I'm going to do the same thing with an eq operator. An eq utility which takes a y and it takes an x, and then it returns us the equality comparison of those two.
[00:01:21] These two kinds of utilities, which take their inputs individually, rather than passing x, y at the same time, taking them in two separate function calls. We already saw a brief example of that, and the question that was asked earlier, is this sort of currying? Yes, this is basically a manual form of currying, we'll get to that.
[00:01:40] But I'm saying I want the y input first and then the x. And I want to make a point about that before we move on. Remember that I said earlier, functional programmers care a lot about the shape of their functions. It matters not just what kinds of inputs a function receives, but what order they're listed in.
[00:01:59] Because if you list them in a different order, guess what people are gonna have to do to use your function every time? Flip it, or use reverse orgs or something. You make it less ergonomically friendly to use when the inputs are listed in an unnatural order. So it matters what order.
[00:02:15] And what you're going to see here is actually, there's an order that is much more natural, which is yx instead of xy, and yx instead of xy for the equals function as well. So that's why I've listed them in that particular order. Okay, so let's take a look at how we can use this mod and this eq function to define.
[00:02:39] Remember we defined is even in terms of as odd. But what if we wanted to define is odd in a point free way. Remember, is odd was defined as x mod 2 = 1. If we had these two utilities in play, couldn't we define is odd in terms of those two functions?
[00:03:03] So, I'm gonna take mod2, mod(2), that's gonna return me back a function, right? Where the y has been provided, but the x still needs to be provided. And I'm gonna call that function mod2, because that function takes any input and mods it with the number 2. And then I'm gonna call eq(1) line 13.
[00:03:28] And that makes an eq1 function, whose job is to take any input value and compare it to the value 1 is equal to 1.
>> Kyle Simpson: Quick little foreshadowing to stuff we're gonna talk about earlier. Do you see that the mod2 function on line 12 is more specific than the general mod to function on line 1?
[00:03:53] The general mod function on line 1 takes two inputs, the mod2 function on line 12 only takes one input. Cuz it's got one of them already prespecified. That's a more specialized function, we'll come back to the idea of specialization later, okay? But I've got a mod 2 an eq1, how can I define is odd in terms of those functions?
[00:04:16] Well, it's actually pretty straightforward. Take the mod2 and pass in the X, and whatever that returns, pass it into eq1.
>> Kyle Simpson: You follow how I did that? Now, that's not point free yet, but we've made a lot of progress moving from operators to functions, okay? So we're halfway there.
[00:04:43] If we want a point free definition of is odd, this is halfway there. We notice that we have this eq1 and this mod2, they're useful to us and we can make those with the mod and eq operators that are provided by our favorite library. But we can also notice something interesting and this is yet another future thing that we'll talk about later in this course, which is the output of the mod2 call is passed directly to the eq1 call.
[00:05:10] Everybody see that? That concept of having one function call's output immediately become the input to another function. That is a special name in programming, that's called composition. Again, throwback to a math class, you may have heard somewhere, like fs of g, or f compose g. That's all a mathematical idea, and here we see it in programming.
[00:05:35] Take one function's output, and make the input to another function. So how can I use the idea that this is a composition pattern to my advantage to make a point free definition? Well, if I had a compose utility, here's my is odd, if I had a compose utility, whose job was to do the routing of one functions output into another functions input.
[00:06:03] Now line 14, I just defined is odd as the composition of the eq1 and the mod2 function. Line 14 is my point free definition for is odd. It's doing under the covers, mod2 is fn1, which is called with whatever value passing to it, that's line 10. So mod2 here is this function.
[00:06:33] And if we pass in a value into is odd, it will come in to mod2. Whatever that output is would come into fn2, which is eq1, and eq1 is going to return us a true false just like we want is odd to return, okay? How am I able to make that analysis?
[00:06:52] This is more equational reasoning, that the function composed here is the same shape as is odd, isn't it? Look at those two, look at composed with an fn1 and an fn2 and look at is odd with an fn1 and an fn2. Look at the input x, look at the input v, look at the return value and the return value.
[00:07:16] Those two are interchangeable, which is what lets me know that line 14 is my point free definition. I simply call compose, and I get back the equivalent function, that's the equational reasoning. And we have one last equational reasoning trick up our sleeve, which is on line 1 and line 2, I defined those intermediary functions mod2, and eq1.
>> Kyle Simpson: But now I can see that eq1 could be replaced with eq(1). And mod2 could be replace with mod(2). So my final point free definition looks like line 16. Those pieces are interchangeable because they have the same shape. That's equational reasoning, and equational reasoning is the heart of being able to do point freestyle.
[00:08:11] It's actually the heart of a bunch of functional programming, but especially point freestyle. Asking yourself if I have this function and I need to make this function, what kind of shape change needs to occur so that they are interchangeable?
>> Kyle Simpson: I'm pretty sure that at some point along the way we crossed that line, for all of you were like, I never would have come up with that.
[00:08:35] At least that's how I was. When I first saw this, I was like, woah, we just went way beyond what I thought was, like, I'm tracking with the readability and now I'm lost. And now I will just tell you that having spent time practicing this, and I'm fortunate enough that as a teacher, I get to re-explain it and re-show it, and re-code it over, and over, and over, again, and that's my practice.
[00:08:55] But in being able to practice this, I will tell you that not only can I read line 16 and understand it, line 16 is more readable to me than line 5. I've gotten to the point where that familiarity level has switched to where the point free functional style is actually more readable to me.
[00:09:15] And whenever I see something like line 5, immediately my brain says that's a composition, you should be using compose there. I didn't get there overnight. It didn't happen in a week, it didn't happen in a month. But over a period of time of practicing these techniques, you become more familiar with those patterns and they sort of jump out at you just like you see the Legos in the pile, and you say no, I know exactly what Legos I need.
[00:09:38] That's the heart of being a functional programmer, is getting used to that being able to recognize that, and then being able to read a lot stuff like line 16 and have it make complete sense.