kotlinlambdaanonymous-functionshorthand

Return Type: Calling a function inside Vs outside `println()`


I'm new to Kotlin.

I was experimenting with Anonymous functions a little bit until facing different outputs for the same concept using different approaches.

var greetingFunction = { playerName: String , numBuildings: Int ->
    val currentYear = 2022
    println("Adding $numBuildings houses")
    "Welcome to SimVillage, $playerName! (Copyright $currentYear)\n"
}
private fun runSimulation(playerName: String, greetingFunc: (String, Int) -> String){
    val numOfBuildings = (1..3).shuffled().last()
    println(greetingFunc(playerName, numOfBuildings))
}

A- Regular call for Anonymous function:

println(runSimulation("Ahmed", greetingFunction))

Output:

Adding 3 houses
Welcome to SimVillage, Ahmed! (Copyright 2022)

B- Shorthand call for Anonymous function:

println(runSimulation("Different") { playerName: String , numBuildings: Int ->
    val currentYear = 2022
    println("Adding $numBuildings houses")
    "Welcome to SimVillage, $playerName! (Copyright $currentYear)\n"
})

Output:

Adding 2 houses
Welcome to SimVillage, Different! (Copyright 2022)

kotlin.Unit

I tried to remove the println() and calling the runSimulation function directly and the output was:

Output:

Adding 2 houses
Welcome to SimVillage, Different! (Copyright 2022)

What I really want to know is: how in the first place did I get that "kotlin.Unit" print using the Shorthand Syntax?


Solution

  • Kotlin will automatically infer the type of lambda expressions. Since the last line of greetingFunction is a String

    var greetingFunction = { playerName: String , numBuildings: Int ->
        val currentYear = 2022
        println("Adding $numBuildings houses")
    
        // the last line is a string -> Kotlin will infer that the return type is a String
        "Welcome to SimVillage, $playerName! (Copyright $currentYear)\n"
    }
    

    the inferred type is

    var greetingFunction: (String, String) -> String
    

    Return types for block-body functions are not inferred. If a function does not return a useful value, its return type is Unit. The function

    private fun runSimulation(playerName: String, greetingFunc: (String, Int) -> String) {
        val numOfBuildings = (1..3).shuffled().last()
        println(greetingFunc(playerName, numOfBuildings))
    }
    

    will therefore return Unit, so

    println(runSimulation("foo") { _, _ -> "bar" })
    

    will print the returned value of runSimulation(), and Unit.toString() is kotlin.Unit

    Since runSimulation() will also print to stdout, this is effectively the same as running

    println(println("bar"))
    

    First the 'inner' println() will output bar, and then the 'outer' println() will print kotlin.Unit.

    bar
    kotlin.Unit