Higher Order Functions8:22 with Craig Dennis
A function that accepts another function is one way to create what is known as Higher Order Functions. It allows you to create extensible code. Let's get some experience writing one.
Functions are first class citizens now, and we have been using them as arguments 0:00 to methods on the stream class that accept them, like map, filter, and foreach. 0:04 So the method declaration on stream for map declares that it accepts a function. 0:08 Methods or functions that accept other functions are called 0:14 higher order functions. 0:17 We can make those two, and they're really great for software design. 0:20 You might have heard about the open close principle of software design. 0:23 The principle states that classes should be open for extension, but closed for 0:27 modification. 0:31 Now the goal is to not keep changing your underline class 0:32 every time a new case is introduced. 0:35 Accepting a function is a great way to not modify your code base, 0:38 because you're keeping the logic encapsulated outside. 0:42 This concept is known to make people's heads spin a bit. 0:46 So hold on for a second, it'll make sense with some practice. 0:49 So let's create a problem for ourselves that will make this more clear. 0:52 Let's assume that we have some sort of service setup 0:57 that watches the indeed stream of job postings. 0:59 And a method is kicked off every time one is published. 1:02 A certain criteria is matched, we wanted to email us. 1:05 Now the problem is, that criteria might change if we see too many jobs or too few. 1:09 Now take some tweaking to get the criteria just right. 1:14 Now we could code that criteria up in our email method. 1:18 Or we could make it accept a function that determined if it should be used or not. 1:21 Here, check this out. 1:27 Okay, so let's clear out our explorer methods, so we got some exploring to do. 1:28 Okay, so first thing's first. 1:35 Let's define our methods, so we'll just add it right here. 1:37 So we need, we'll make it public, and we'll make it static. 1:41 And the method's gonna return nothing. 1:44 It's gonna send an email, so we'll just make this void, and 1:47 we'll call this emailIfMatches. 1:50 So what we'll do is we'll pass in the job. 1:52 And now, we need to find out if the job is something that we wanna be 1:59 emailed about, right? 2:03 So we'll run some sort of check on the job, and then we'll return true. 2:04 But like I said, these requirements might change a lot, so 2:08 we should allow our caller to define things. 2:11 So we wanna take in a job, and return whether or not it matched. 2:15 So a boolean, a true, or a false. 2:18 Now lucky for us, we have that exact same shape, remember? 2:21 It's called a predicate. 2:24 So what we want is we want a predicate of jobs, and 2:25 we'll call it checker, except spelled right. 2:30 And now inside the method body, we wanna know if the job matches. 2:36 So the predicates abstract methods name is test. 2:41 And so what we'll do is we'll call checker.test. 2:47 And it's going to take a job, It'll take the job that we passed in. 2:51 So then in the body, if that returns true, 2:56 we'll do more complex email instructions, but for now, we'll just, we'll fake it. 2:59 Let's say, I am sending an email about, and then we'll just print out job here. 3:05 You know what? 3:14 Let's do this. 3:16 Let's say that we want to email us about any job at all in the State of California. 3:16 So let's just pull some random job, maybe it won't be from California, let's see. 3:22 So let's say job, the firstOne = jobs.get(0). 3:25 Okay, and we'll see where that's from. 3:33 Say, First job, and we'll print that out. 3:35 And that job, we'll print out the first one. 3:40 And now let's call our new method, passing in that random job. 3:44 So we'll say emailIfMatches, and we're going to pass in that firstOne. 3:48 And now we needed to find our predicate. 3:55 So we need a job that is in the State of California. 3:58 So job.getState().equals("CA")), 4:04 that is the state code for California. 4:10 And there we have it, right? 4:16 So we have a method that takes a function as a parameter, 4:18 and that's a function with the lowercase f. 4:23 And we have just made a higher order function, so let's run it. 4:25 And so it's just printing out this first job line, but 4:30 you'll notice that it is in Texas. 4:33 Our first job's in Texas, and therefore, we didn't get emailed. 4:35 So we're working on the false case. 4:38 But now, let's verify that it works, right? 4:40 So now we need to verify that it actually works, and there's a job from California. 4:43 So let's do that. 4:46 Let's extract this variable here. 4:47 And let's turn that into a variable, since we don't wanna repeat ourselves, right? 4:50 So we are gonna call that caJobChecker. 4:55 So now, let's go find our first California job that we come across. 5:00 So let's do that. 5:07 So we'll say jobs.stream, and we need to filter. 5:08 And remember, filters take predicates. 5:12 Hey, so we got one of those sitting right there. 5:14 So we just reuse it, we didn't repeat ourselves, did we? 5:16 And then let's get the first one. 5:18 And I am pretty sure that unless Silicone Valley dries up, 5:22 there's always going to be a job. 5:27 So let's just go ahead and say or else throw, and 5:30 you can do this actually, this is kinda neat. 5:33 You can do NullPointerException, and we'll do new there. 5:36 So we'll just throw a null pointer if it doesn't exist. 5:39 It's gonna exist, there's gonna be a job in California. 5:42 Okay, so do you see what this is doing here? 5:45 This is a method reference to the constructor, right? 5:48 So you can pass a new there, pretty powerful. 5:51 Okay, and then let's do, let's run our function again. 5:55 Let's assume that there is a new job posting. 5:57 We're just gonna pretend that this CA job came through. 6:00 We'll run that, boom, and there it is. 6:05 It's now sending an email. 6:09 See, I'm sending an email about a job that's in California. 6:10 Nice, we did it. And 6:13 we can pass any predicate into this email function. 6:14 And it'll send it out without ever touching the email method, right? 6:17 So it's outside. 6:21 So we did a really good job with that open close principle. 6:23 It's pretty powerful, right? 6:26 So at first though, 6:27 this method of only accepting a single predicate might seem a little bit limited. 6:29 But don't worry, you can actually logically combine 6:34 different predicates to return a new predicate. 6:37 For instance, let's say that I'm getting overwhelmed by the jobs coming in from 6:39 a California emailer. 6:43 And I wanna make sure that I just have junior jobs from California. 6:45 But we can do that fairly easily using a default method that predicate provides. 6:49 And that's called AND. 6:54 Okay, so this is not a junior job. 6:55 It doesn't say junior in the title. 6:58 So let's go ahead and we'll say if it matches .and. 6:59 And since we already have a static method that says, is junior job, 7:06 we can just use it, right? 7:09 So, we can say, App ::isJuniorJob, right? 7:10 And that's gonna pass in the junior job. 7:15 So this and is very much the logical and. 7:18 So, it's like, if this is true and this is true. 7:21 And if we run it again, we'll see that that job doesn't get emailed out. 7:26 Cool, right? 7:32 And remember, isJuniorJob is a method that is not a predicate, it's just matching it. 7:33 Let's find it. 7:39 Let's find isJuniorJob. 7:40 So here it is, it's it. 7:45 It takes an object, and it returns a boolean. 7:46 It takes a job and returns a boolean. 7:48 Which is why we were able to join those two together, right? 7:50 So it takes a job, passes that job through into that. 7:53 Super cool, right? 7:56 So this combining is known as another term that we have over on our parking lot, and 7:58 that is functional composition. 8:02 So we just did higher order functions. 8:05 We made a very nice powerful higher order function. 8:09 Let's strike that through. 8:12 Getting close to the end of our list. 8:14 So let's take a deeper look at what we can do with functional composition, 8:17 right after this quick break. 8:21
You need to sign up for Treehouse in order to download course files.Sign up