Lambdas & Higher-Order Functions

Peter Sommerhoff
A free video tutorial from Peter Sommerhoff
Developer & Software Engineer - With 45,000+ Happy Students
4.5 instructor rating • 6 courses • 62,508 students

Learn more from the full course

Kotlin for Android & Java Developers: Clean Code on Android

Become a professional Kotlin developer and write cleaner code in your Android apps than in Java, avoid boilerplate code

09:14:18 of on-demand video • Updated November 2020

  • Write clean code with Kotlin
  • Avoid ceremony and boilerplate code around Android APIs
  • Use functional programming to write concise, expressive code
  • Create Android apps with Kotlin
  • Write readable SQLite transactions using extension functions in Kotlin
  • Use the Kotlin Android Extensions to avoid findViewById()
  • Create multiple activities, layouts and menus
English Instructor: Now that you know what functional programming in general actually refers to, and what the major parts or concepts in functional programming are, let's start our journey into functional programming in Kotlin by diving right into lambdas and higher-order functions. So, for that I'm gonna go ahead here again in our project structure, create a new file, and I'm just gonna call that lambdas. And I will also again include a main function here first of all so that we can just try out what we do in here. And now first of all, let's go ahead and take a look at how to actually create a lambda. And you can think of a lambda function as just a function without a name. So, you can just create a function like this. You first use curly braces to define the lambda, then next you can go ahead and define the parameters of the lambda function. In this case I'm gonna say it takes an integer, X. Then use an arrow and define the return value of the lambda. In this case I'm gonna say X times two. So, this is now a lambda function here which has one parameter of type integer, and it's just gonna multiply that number by two. Next thing you can do now is you can store that function into a variable. In this case let's say timesTwo. So, now the variable timesTwo here has actually a type function, and you can write this out explicitly as well as a function that takes an integer and returns an integer as well. But we're also gonna have to wrap all the input parameters in parentheses to make sure that this is actually a function type. But again, you can also get rid of this for now because Kotlin can infer that type for us. So, let's go ahead and just remove that for now to clean up the code a bit. And you can also go ahead and create a lambda with more than one parameter of course. And in that case you can just separate them by comma. So, for example, X and Y, and just return X + Y for example. And again, the return type here is gonna be a function that takes in two integers and returns an integer again. And that's the way you can write this in Kotlin using parentheses to define the input parameters, also separating them by a comma, and then the arrow to define the return type on the right-hand side. Again, you don't need to do this here, but it's just to show you what the syntax of the type declaration would actually look like. So, now that you know how you can create lambdas, let's take a look at higher-order functions in Kotlin. And for that I'm first gonna go ahead and create a list. And I'm gonna construct that as a list of elements one to a hundred, and then put that into a list. So, this is gonna generate the range of numbers from one to a hundred, but I wanna actually wrap that into a list. So, I can call the toList() method on that. And this way I'm gonna get a list of all numbers from one to a hundred. And now, one of the built-in higher-order functions in Kotlin is this filter() function on collections here. Which, as you can already see, takes in a predicate. So, a function that returns a boolean, and it's gonna take in one integer in this case because we're having or we're calling this on a list of integers. So, it's gonna take in one integer and it has to return a boolean. So, notice here again the same syntax with the parameters or the input parameters of the function in parentheses, then the arrow and the return type. So, you can see that this filter() function here is a higher-order function because it does actually take in another function as its argument. Another way for higher-order functions is that they return a function. And of course, they could also take in functions as parameters and also return functions again as their return type. In this case you're gonna take a look at this filter() function which is a higher-order function that just takes in another function as a parameter. So, how are you gonna pass in a function like this? Well, we can again create a lambda. So, curly braces, and then we're gonna have one argument here. In this case, we're gonna call that element. But you can call it whatever you like. And it is actually gonna be of type integer, but again the Kotlin compiler can infer the type here because we do actually need a lambda from intoBoolean. So, it's gonna assume that the type of this is gonna be int. And then what we can do is we can for example filter out all the numbers that are not even. So, I'm gonna say filter element modulo two is zero, meaning that the element is divisible by two. So, in those cases it won't be removed from the list or from the return value of the function call. But if it is an odd number, it's not gonna be in the result of this filter. So, if you print this out, it's only gonna return the even values. And let's actually go ahead and give this a test run just to make sure that we do get the expected result. Alright, so as you can see, we only get all the even numbers returned, which is exactly what we wanted to do. So, this is working fine but it's still a bit lengthy. And this is more like the Java way to write a lambda with having the input type here, or the input arguments, on the left-hand side and then the right-hand side. So, let's go ahead and actually make this a bit shorter. And to do that, we can actually make use of the implicit it variable which exists if the lambda expression, like in this case, has only one parameter, in this case the element, then we can get rid of the left-hand side and the arrow and just refer to the element that we're currently looking at using it. So, this is a variable that is implicitly created by Kotlin. And you can use this whenever, as I mentioned, you only have one parameter in the lambda. So, now we can say a list.filter, it modulo two equals zero. Or we can make this a bit more readable again by wrapping this modulo function here into its own function call. And actually, the nicest way to do this is to actually use an extension function here on the int type. Let's say Int.even() again, I think we had this before, is equal to this modulo two equals zero. And then this way we can again improve this code up here by actually going ahead and using it.even() because it is a integer variable, and so we can now use our extension function on that. So, this way now we have very concise and very readable code which is often the case once you actually apply all the nice features you can use in Kotlin. Now, I wanna show you one more thing you can do by having a function, let's say isEven() which is gonna take an integer and is also just gonna return whether I modulo two equals zero. Then you can also make use of so-called function pointers to pass in the function that you want to filter with. And to use or refer to a function, in this case isEven(), you can first use two colons and then pass in the name of the function, in this case isEven(). And this way now it's gonna apply this function here to each of the elements. So, this is basically just another way to write this. And to refer to a function like this, you're gonna have to use the double colon notation. And of course the signature of this function has to match the function that is expected as an argument. So, in this case it must be a function that takes an integer here and that returns a boolean which of course is fulfilled with isEven here. Now, one last thing we can even improve with this solution here is to make use of the fact that in Kotlin, if a function, like filter() in this case, takes in a lambda as its last argument, we can move that lambda expression out of the parentheses here and just use it like this. Now, let me just get rid of the println for a moment just to make this structure a bit clearer. So, you can see now for calling the filter function here, we don't actually use any parentheses anymore, we just define the lambda. So, basically we can move this out of the parentheses because in this case the lambda is actually the only parameter, so of course it's also the last parameter. So, especially in more complex use cases, this is a very neat way to write the lambdas and to actually structure your code. And we're also gonna see in a few lectures later how you can also make use of this to create functions that look a bit like as if they were keywords. And which also help make your code much more readable and concise. Alright, so those are the basics of lambdas and higher-order functions in Kotlin. And as an example, we already looked at the filter() function for collections. And we're actually gonna move on in the next couple lectures to look at other methods or higher-order functions on collections in more detail so that you can really work with collections very effectively in Kotlin. But for now, the main takeaways of this lecture are how to create lambda expressions, and then that you can actually use the implicit it variable here if a lambda expression only has one parameter. And also that you can move out the lambda expression of the argument or the function call if it's the last argument. So, with this we're now ready to go ahead and dive into the next couple lectures to look at other useful functions beside the filter() function. So, thank you very much for watching, and I look forward to seeing you again in the next lecture.