Despite visual similarity, the idea of these two declarations is completely different.
1. Function declaration without equals sign
Function declaration without equals sign is a Unit
-returning function (similar to Java's void
functions).
What's inside the curly braces is its body, which gets executed right on the function call. The function can be rewritten with Unit
explicitly specified:
fun foo1(): Unit {
println("baz1")
return Unit
}
Kotlin doesn't require the return statement and explicit return type for Unit
-returning functions, and both are usually omitted.
2. Function declaration with equals sign
Function declaration with equals sign is a single-expression function, and what it does is just return what's to the right of equals sign.
A simpler example: fun getInt() = 1
is just a shorter form of fun getInt(): Int { return 1 }
.
In foo2
, the right hand side is a lambda expression. The code inside the lambda code block is not executed. In other words, foo2
is a function that returns another function.
Return type of foo2
is () -> Unit
, a function itself, and thus foo2
is a higher-order function.
Without the syntactic sugar and with explicit type, foo2
can be rewritten as
fun foo2(): () -> Unit {
val result: () -> Unit = { println("baz2") }
return result
}
As to the usage, the function which foo2
returns can be stored in a variable, passed around and can later be invoked:
val f = foo2()
f() //equivalent to
f.invoke()
This is also why foo2()()
in the example executes the code from the lambda body.
Alternatively, we can add ()
at the end when we declare foo2(), as shown in the following example. As such, the lambda expression will be invoked when calling foo3()
. But this is not a good pattern.
fun foo3() = {
println("baz3")
}()