Don't let Kotlin's single-expression function ruin your businessšŸ˜²

Take care, Keep building!

Don't let Kotlin's single-expression function ruin your businessšŸ˜²

Hello developers šŸ‘‹,

This is a mini-blog where we'll see how a small mistake can lead to a confusing and serious issue.

Kotlin provides us with a way where we can define single-expression functions for one-shot operations. For e.g. we do something like this šŸ‘‡

fun getItemById(id: String) = repository.findItemById(id)

The return type of the above function will be the return type of the result of findItemById(), right? In the single-expression function, we donā€™t have a need to specify return type since itā€™s automatically inferred by Kotlinā€™s compiler.


The real problem šŸ˜¬

One day I was playing with Kotlin and while doing it I came across an issue that was actually produced by my own mistake. This issue looks small but it took me some time to came to know about it.

Now letā€™s understand how can our mistake lead to the issues. So refer to the below code.

fun greetGoodMorning() {
    // Some code
    println("Good Morning")
}

fun greetGoodAfternoon() = {
    // Some code
    println("Good Afternoon")
}

fun main() {
    greetGoodMorning()
    greetGoodAfternoon()
}

// Output:
// Good Morning

WhatšŸ˜•? Just Good Morning? Why Good Afternoon isnā€™t printed?

You can execute this code by clicking here


How? šŸ¤”

Did you notice = {} in greetGoodAfternoon() function? So this where the problem comes from. Letā€™s understand the issue.

So any developer wonā€™t be intentionally writing such code. It may be just like we introduce typo mistakes! As we know, in a single-expression function, the returning type of a function is automatically inferred by the compiler (if not specified explicitly). When we write = {}, its return type is inferred internally as this šŸ‘‡

fun greetGoodAfternoon(): () -> Unit = {
    // Some code
    println("Good Afternoon")
}

Yes, itā€™s inferred as a lambda block šŸ˜…. So when we called greetGoodAfternoon() it returned a lambda! If we call greetGoodAfternoon().invoke() or greetGoodAfternoon()() then itā€™ll be get executed (Because you now know what happened šŸ˜„).

Note: IntelliJ IDEA or Android Studio warns you if you do such mistakes. But even after that if you ignored it, no one can help you.


Solution šŸ’”

We are humans!šŸ˜Æ We always will do mistakes but thatā€™s fine. The mistake which we did above (= {}) canā€™t be solved using any manual way. But there are some learnings by which we can avoid other related issues.

In my opinion, good practice to avoid mistakes will be a habit of mentioning return types explicitly! Yes, if we mention it explicitly (even if using a simple-expression function) then itā€™ll avoid mistakes then weā€™ll be sure about such things at compile time itself.

fun getItemById(id: String): Item = repository.findItemById(id)

By this, we can be sure that this function is returning Item. If not, then the compiler will be there to help you out. It makes code more readable and also we can be sure about it just by reading it (like what exactly function is returning). It can help the reviewer while reviewing code on GitHub as well šŸ˜Ž.

For a simple, one-liner call that doesnā€™t return anything, then this is fine šŸ‘‡

fun printSomething(something: Any) = println("$something")

Thereā€™s no doubt that Kotlin has made developerā€™s life simple and easy. But anyone can do such mistakes.

So the final conclusion is šŸ‘‡

Mention return type of a function explicitly and make it a habit!


If you liked this article then share it with everyone! Maybe itā€™ll help someone who needs it.

Thank you šŸ˜ƒ


Many thanks to Siddhesh Patil and Niharika Arora for helping me to make this better! šŸ˜ƒ

Did you find this article valuable?

Support Shreyas Patil by becoming a sponsor. Any amount is appreciated!

Ā