用lambda参数链接方法是什么?
我正在研究Kotlin编码挑战,并提出了一个类似这样的解决方案:
val x = listOf(1, 2, 3) .fold("") { acc, i -> acc + someLookupFunction(i) }.let { // something }
以上是我希望如何格式化。 但是,使用IntelliJ自动格式化程序时,它坚持认为代码应该如下格式化:
val x = listOf(1, 2, 3) .fold("") { acc, i -> acc + someLookupFunction(i) }.let { // something }
我的第一个想法是,这是一个错误,但实际上我认为这只是模糊的。 格式器必须认为let
是lambda本身的函数调用,而不是fold
的结果。 为了证实这一点,我改变了这个:
val x = listOf(1, 2, 3) .fold("", { acc, i -> acc + someLookupFunction(i) }).let { // something }
而Intellij格式化了我的期望。 所以这就引出了我的问题 – 在使用类似lambdaexpression式的链式方法调用中是否存在官方约定? 链接时是否应该使用显式的parens以避免含糊不清? 这实际上是Intellij应该报告的错误吗?
Kotlin文档有一个关于编码风格的章节,包括链式调用的包装 :
链式呼叫包装
当包装链接的电话时,把。 性格还是? 下一行的操作符,带有一个缩进:
val anchor = owner ?.firstChild!! .siblings(forward = true) .dropWhile { it is PsiComment || it is PsiWhiteSpace }
链中的第一个调用通常应该在它之前有一个换行符,但是可以忽略它,代码更有意义。
所以我可能会这样改变它:
val x = listOf(1, 2, 3) .fold("") { acc, i -> acc + someLookupFunction(i) } .let { // something }
要么:
val x = listOf(1, 2, 3) .fold("") { acc, i -> acc + someLookupFunction(i) } .let { /* something */ }
IntelliJ提出的格式是正确的,因为当lambda是函数的最后一个参数时,lambda可以从方法的括号中提取出来。
所以IntelliJ不认为let
是lambda本身的一个函数调用,它只是另一种编写相同的代码的方式,就像你期望的那样(你的第三个代码片段)。
从Kotlin官方文档 :
在Kotlin中,有一个约定,如果函数的最后一个参数是一个函数,并且传递一个lambdaexpression式作为相应的参数,则可以在括号外指定它。 […]这些约定允许编写LINQ风格的代码:
strings.filter { it.length == 5 }.sortedBy { it }.map { it.toUpperCase() }