用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() }