考虑这里给出的示例: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()) }
和这段代码:
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 }
}
看来我们的努力是为了避免写几个括号,冒着让读者感到困惑的风险。 如果保持标准不是更好吗?使用第二个示例中的函数的通常方法是:
convert(20, {it * 1.8 + 32})
convertFive({it * 1.8 = 32})
但是 IntelliJ 会抱怨并建议将 lambda 从括号中移出。为什么?有实际好处吗?看起来像是写
10 + 2 * 5 / 34
而不是 10 + (2 * 5) / 34
。
尾随大括号 lambda 的真正好处在于,像所有最好的语言功能一样,它改变了您的思维方式。
您提供的示例用括号编写得很好,我同意 IntelliJ 建议始终使用尾随形式是不必要的......
但是当我写下这样的东西时:
with(someObject) {
doSomething();
doSomethingElse();
}
它看起来就像我正在使用该语言的一个很酷的新功能,即使我实际上只是调用一个函数。
结果是,人们开始思考他们可以编写向语言添加东西的函数,因为他们有点可以,这导致他们为使用他们的代码的人创建新的做事方式。
类型安全构建器模式就是一个很好的例子。许多 Kotlin 语言功能协同工作,因此,即使它只是调用函数和传递 lambda,它也为使用它的开发人员提供了新的体验。
他们获得了一种全新的方式来实例化复杂对象,这种方式比旧方式更加自然,并且不需要为此在语言中添加任何内容——所有的小构建块功能都可以用于许多其他事情。
根本没有任何实际好处,只是一个约定。
关于你所说的“保持标准”。你到底从哪里得到“通常的方式”?据我所知,没有全局编程约定,只有特定于语言的约定,因此这种表示法根据定义是标准的。
约定很重要,因为它们可以让熟悉语法的人更轻松地阅读代码。这些约定也反映了语言的用法。通过 Kotlin,他们提倡一种非常实用的风格,大量使用 lambda 和内联函数,因此“括号外的 lambda”对于保持代码干净和明确是必要的。
正如@Tenfour04 在评论中所说,您的示例确实没有反映语法的预期用法。一般来说,你有多条线,即使没有,图案也应该传达更多的东西。以
measureTimeMillis
函数为例:
measureTimeMillis {
askQuestion()
comment()
answerQuestion()
}
通过将 lambda 放在括号之外,即使对于非技术读者来说,也可以立即清楚该函数的作用,这正是约定的用途。
更接近你的例子。假设您需要转换一个数字数组并对所有正数进行平方。比较一下更容易阅读的内容:
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
}
}