Function references are another of those great improvements that we get with Kotlin, which are kind of exotic when we come from Java.

You already know that Kotlin supports as a type, what means that you can save a function in a variable, use it as another function argument, or even make that a function returns another function.

This is the main feature to consider that a language supports functional programming style, and Kotlin of course allows this. You can declare a function in a variable like this:

See? This is a function that receives two integers and return one integer. In this particular implementation, the lambda is applying an addition operation.

You could then have a function that accepts a lambda of this type as an argument:

This is taking two integers and applying the function to both, so you can use the combination of both this way:

Easy, right? You probably knew about this already. But I’m gonna show you something interesting now:

Function references: any function can be a lambda

So the same way can be passed as an argument or saved to a variable, we can do the same with regular functions.

Thanks to function references, our code can become much cleaner, and we can apply functional style to libraries or frameworks (can you think of any? 😝) that use just plain functions.

I’ll first explain it with the example above. Imagine that instead of a lambda, you have a plain function:

This is doing the same, but instead of having a variable that keeps the function, we just have a function. Now, if you look at the call above, it is failing:

sum is not detected as a lambda, it just expects to be called as a regular function. But if you think about it carefully, it keeps the same structure: it receives two integers and returns one. What are we missing?

We need to use the function reference. For that, you only have to prepend two colons to the name of the function:

And done!

So that you get the complete idea of this, a function reference behaves as a lambda, and as such, you can assign this reference to a variable with the same structure:

Awesome, right? But let’s see this in some more practical cases.

Putting functional references into practice

If it’s the first time you see this, you may be wondering what gives you that you didn’t have before. Fair question, let’s see some examples.

Imagine the typical example where you receive some to update the UI, but you only need to do it in the case the is not null. The most direct approach would be:

If you already know about the let function, you’ll agree with me that this looks a little better:

But let’s think on this for a moment… If you check the structure of the let function (don’t worry if you don’t understand everything):

It’s a function that receives a lambda with two arguments: T and R. In our particular case T would be Data and R is Unit, as we’re not using the return value of let for anything. So it would look like this after computing the generic types:

Remember about the function applyUiChanges? It receives Data and returns nothing (what it’s the same as Unit), so it conforms with the structure that the let function is expecting. So why don’t we call the function instead?

W00t! If you think about it this is much cleaner, and explains better what it’s happening. It’s true that first times it may look a little strange, but as soon as you get used to it, you’ll love it.

As the function is a member of the class, that’s why you need to prepend this to the call.

Things will get even better in Kotlin 1.2, where you can get rid of this:

The rule of thumb: when in a lambda we use a function that receives all the input values of the lambda as arguments, then you can just use the function reference.

But let’s go beyond!

Lambdas with more than one input value

Of course, this works with any amount of values. Imagine that you have an observable delegate like this:

As you see, we cannot just use the reference to the function because notifyChanges doesn’t have the same structure. It’s only receiving two values instead of three. But just by changing the structure of the function a little:

Now we’re able to use the reference instead:

Property references

References are not only restricted to functions. Properties in the end are a functions that return a value (think of them as the getters in Java), so why not using them?

Let’s say we have a data class called MediaItem :

And that we want to print a list of urls sorted by the title of the item (You can check more about functional collection operations here):

In my opinion, this is is easier to read than the counterpart with explicit lambdas:

Looking at the bytecode

You might be wondering if there’s any difference in bytecode, and if one of the options is more efficient than the other. So let’s use the Kotlin bytecode tool for the previous example and check it out.

This is the bytecode for the one with explicit lambdas:

And this for the one with function references:

Unsurprisingly, the code is pretty similar. With the function references we’re saving ourselves from a couple of variable declarations, which correspond to the it variables inside the lambdas. So we can say it’s a little more efficient, but honestly nothing to worry about.

Should I use function references in my code?

Function references are a cool new feature that can clean up code and do it more semantic.

But this comes at the cost of increasing the learning curve. It’s something Java developers are not used to, and because of that, new Kotlin adopters can find them a bit obscure at the beginning.

But hey! You can always link them to this article, and have them writing them in a few minutes 😄

Did you know about function references? Have you used them in your projects? Let me know in the comments, and if you’re in the process of learning Kotlin, you may be interested in my online course.

Author: Antonio Leiva

I’m in love with Kotlin. I’ve been learning about it for a couple of years, applying it to Android and digesting all this knowledge so that you can learn it with no effort.

Source link
thanks you RSS link


Please enter your comment!
Please enter your name here