Reputation: 23
Consider this example given here: https://stackoverflow.com/a/53376287/11819720
fun onClick(action: () -> Unit) { ... }
view.onClick({ toast(it.toString())} )
view.onClick() {toast(it.toString()) }
view.onClick { toast(it.toString()) }
and this code:
fun convert(x: Double, converter: (Double) -> Double): Double{
val result = converter(x)
println("$x is converted to $result")
return result
}
fun convertFive (converter: (Int) -> double): Double{
val result = converter(5)
println(" 5 is converted to $result")
return result
}
fun main (args: Array<String>){
convert(20.0) { it * 1.8 + 32 }
convertFive { it * 1.8 + 32 }
}
It seems the effort is to save on writing a few parentheses at the risk of confusing a reader. Would it not be better if it was kept standard? The usual way to use the functions in the second example would be:
convert(20, {it * 1.8 + 32})
convertFive({it * 1.8 = 32})
but IntelliJ will complain and suggest moving the lambda out of the parenthesis. Why? Is there a practical benefit? Seems like writing 10 + 2 * 5 / 34
instead of 10 + (2 * 5) / 34
.
Upvotes: 1
Views: 2245
Reputation: 131
Closer to your example. Let's say you need to convert an array of numbers and square all the positive ones. Compare what is easier to read:
val result = arrayOf(1.0, 2.0, -3.0).map({ number ->
convert(number, {
if (it > 0) it * it else it
})
})
val result = arrayOf(1.0, 2.0, -3.0).map { number ->
convert(number) {
if (it > 0) it * it else it
}
}
Upvotes: 1
Reputation: 59358
The real benefit of the trailing-braces lambda is that, like all the best language features, it changes the way you think.
The examples you have provided are just as well written with parentheses, and I agree that the IntelliJ suggestion to use the trailing form all the time is unnecessary...
But when I write something like this:
with(someObject) {
doSomething();
doSomethingElse();
}
It looks like I'm using a cool new feature of the language even though I'm really just calling a function.
The result is that people start thinking like they can write functions that add things to the language, because they kinda can, and that leads them to create new ways of doing things for the people who use their code.
The type-safe builder pattern is a great example of this. A lot of the Kotlin language features work together so that, even though it's just calling functions and passing lambdas, it provides a new experience for the developers that use it.
They get a whole new way to instantiate complex objects that is much more natural than the old ways, and nothing needed to be added to the language just for that -- all the little building-block features can be used for many other things.
Upvotes: 3
Reputation: 5990
There is no practical benefit at all, it is just a convention.
In regards to what you said about "keeping it standard". Where exactly did you get the "usual way" from? There are no global programming conventions that I am aware of, only language-specific ones, so this notation is standard by definition.
Conventions are important as they make reading code a lot less effort for anyone also familiar with the syntax. The conventions also reflect the usage of the language. With Kotlin they promote a very functional style with heavy use of lambdas and inline functions so 'lambdas out of parentheses' is necessary to keep the code clean and explicit.
Also as @Tenfour04 said in the comments, your examples really don't reflect the intended usage of the syntax. Generally you have multiple lines and even if you don't, the pattern is supposed to convey something more. Take the measureTimeMillis
function for example:
measureTimeMillis {
askQuestion()
comment()
answerQuestion()
}
By having the lambda outside of the parenthesis it is immediately evident what the function does, even to a non-technical reader which is exactly what conventions are there for.
Upvotes: 1