Reputation: 582
Kotlin has two ways of declaring an anonymous function (aka a lambda). The two different syntaxes are:
val lambda = { input : String ->
"received ${input}"
}
and
val anonymousFunction = fun (input : String): String {
return "received ${input}"
}
I understand the difference between the two (as outlined in this answer), but what I don't understand is why the language has two different ways of declaring the same thing.
Are there optimizations at work under the hood for one verses the other? Was the anonymous function version thought to be too verbose? Could the lambda version of the syntax not support a return type?
Upvotes: 32
Views: 9032
Reputation: 97338
The key reason is the support for returns from lambdas. The rule for returns is that the return
keyword returns from the nearest function declared with the fun
keyword. In some scenarios, you want a return
in a block of code to return from the enclosing function, so you use a lambda:
fun processElements(list: List<Element>): Boolean {
list.forEach { element ->
if (!element.process()) return false // returns from processElements()
}
return true
}
In other scenarios, you want to return from the block but not from the enclosing function. When using a lambda, returning from the block requires the return@label
syntax, which is somewhat clunky:
fun processElements(list: List<Element>) {
list.forEach { element ->
if (!needToProcessElement(element)) return@forEach // returns from block
element.process()
}
}
To avoid the clunkiness, we've provided an alternative syntax - anonymous functions - which allows you to use return
directly to return from the block:
fun processElements(list: List<Element>) {
list.forEach(fun(element) {
if (!needToProcessElement(element)) return // returns from block
element.process()
})
}
A secondary reason is that it's indeed impossible to fit the return type declaration into the syntax of a lambda, but this is very rarely needed in practice, so it's not particularly important.
Upvotes: 43