Kotlin Higher Order Functions Tips and Tricks

With Kotlin, functions are first-class citizens, meaning you can assign them to variables and pass them into functions as parameters. If you have a function that takes a higher order function as a parameter, you can use the function modifier inline to inline the higher order function straight into your function. This is basically just copying and pasting the code to the call site.

Screen Shot 2017-12-28 at 10.01.06.png.png

The performance benefit is typically minimal. You can also mark specific higher order functions to be not inlined with the noinline modifier. As you can see, if we have an inline function that takes a single noinlined higher order function, your IDE should warn you that there will be minimal performance gains (notice inline has a yellow underline).

Screen Shot 2017-12-28 at 10.01.17.png.png

This generally is only useful if your function takes multiple higher order functions and you don’t want them all to be inlined.

Screen Shot 2017-12-28 at 10.01.36.png.png

The other, more important, benefit of the inline function modifier is the ability to reify a generic type. With type erasure, if you have a class that is generically typed, like List<T>, the type of T is lost at runtime and you are unable to query it. So if you had a listOf<Int>(), at runtime you won’t be able to find out what that type is. Kotlin allows you to combine the inline and reified modifiers to make this possible. As you can see below, checking the type of a generically typed function causes a compilation error, as the type will have been erased at runtime.

Screen Shot 2017-12-28 at 10.16.56.png.png

So instead we mark the function as inline, and the generic type as reified. This allows us to query the type at runtime.

Screen Shot 2017-12-28 at 10.17.13.png.png

A thing to keep in mind when using inlined functions is how the return flow changes. Take the forEach function in the Kotlin stdlib. This is an inline function. Let’s take a look at the following code:

Screen Shot 2017-12-28 at 10.21.57.png.png

And I invoke the function with doSomethingWith(listOf(1, 2, 3, 4, 5)). Do you think “Will this print?” will actually print? The answer is no, because the forEach function is inlined, meaning the code is copied and the return statement now returns out of the parent, being our entire function. To get around this, you can use labels like so:

Screen Shot 2017-12-28 at 10.25.36.png.png

Now, “Will this print?” will actually print. You can also define your own labels for readability sake.

Screen Shot 2017-12-28 at 10.25.53.png.png

Next, let’s take a look at a really cool thing we can do with higher order functions – passing in extension functions. Let’s say we define the following function:

Screen Shot 2017-12-28 at 10.32.59.png.png

And when we call it, we get passed back a string and we can access properties and functions on that string, like so:

Screen Shot 2017-12-28 at 10.35.39.png.png

As you can see, we’re accessing ‘it’, being a string, and using functions and accessing properties on it. This is a pretty simple example, but you could imagine a scenario where the parameter you passed in was some other class which had properties which themselves were other classes. You don’t really want to have it. everywhere. So instead, rather than passing in a string to the handler, you can pass an extension on string, like so:

Screen Shot 2017-12-28 at 10.38.14.png.png

And now, when calling this function, because we’re basically creating an extension to String on the fly, we don’t need to use it everywhere.

Screen Shot 2017-12-28 at 10.39.07.png.png

For something like a String, this technique doesn’t really make sense to use as it actually makes your code more difficult to understand. But imagine a class like HttpHandler, which has request and response properties. Rather than doing it.response, it.request, you can just access response and request like that, leading to cleaner code.

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s