The Riddle

And the question is: What does the puzzler() method print and why is it not 42? Assume that the main()method gets executed.

The answer can be found at the very end of the article.

Explanation

In Kotlin, we’ve got not only local variable type inference (which is also coming to Java) but also return value type inference when writing single-expression methods.

Which means that if we write a method:

fun foo() : String {
return "42"
}

We can rewrite it using the single-expression method syntax and ignore the explicit type declaration and the return keyword:

fun foo() = "42"

So, if we have a method:

fun foo(int: Int?) : Unit {
println(int)
return Unit
}

We could get rid of the return type declaration as well as the explicit return statement by leveraging single-expression method syntax, right? But we already know that the following doesn’t work:

fun foo(int: Int?) = {
println(int)
}

The devil’s in the details, but everything becomes crystal clear if we specify the return type explicitly:

fun foo(int: Int?) : () -> Unit = {
println(int)
}

If we look closely, it can be seen that we mixed two approaches here and actually defined a method that doesn’t return Unit, but a () -> Unit itself – which is simply an action that doesn’t accept any parameters and doesn’t return anything – which is semantically equivalent to returning a java.lang.Runnable instance.

This is because Kotlin utilizes curly braces not only for defining classes/methods, but also for defining lambda expressions, and { println(42) } is a valid lambda expression declaration:

val foo: () -> Unit = { println(42) }

So, our original example is simply a Higher-Order Function accepting an Int parameter and returning a function that prints it. When we return it in the forEach(), the return value just gets ignored.

So, if we want to fix our example, we have two ways to go.

Explicitly call invoke() on the returned function:

listOf(42)
.forEach { foo(it).invoke() }

Or simply define the method properly by removing the “=” sign:

fun foo(int: Int?) {
println(int)
}

Or by leveraging the single-expression method syntax:

fun foo(int: Int?) = println(int)

That’s why I encourage my fellow team members to declare return types explicitly.