【问题标题】:What is the benefit in removing parentheses when using Kotlin lambda expressions?使用 Kotlin lambda 表达式时删除括号有什么好处?
【发布时间】:2021-04-06 16:14:41
【问题描述】:

考虑这里给出的这个例子: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

【问题讨论】:

  • 我会说这更像是写10 + (2 * 5) 而不是10 + ((2 * 5)) - 这只是一个约定(在此处引用但没有详细说明原因:kotlinlang.org/docs/lambdas.html#passing-trailing-lambdas)。一旦您熟悉了约定,它就会使代码(可以说)更具可读性,使函数链接更清晰,并且它反映了一些函数式语言的风格。但它是“标准的”,是语言规范的一部分!
  • 惯例是没有括号,所以这是最不可能让习惯 Kotlin 的读者感到困惑的语法。他们选择了在大多数情况下最干净的语法。在您的第一个代码块中,最后一个示例的阅读和解释噪音最小。您的示例是简单的单行代码,但通常情况下,lambda 中有几行代码。大多数人宁愿不必跟踪在所有代码中放置尾括号的位置。
  • 附带说明,10 + 2 * 5 / 34 - 3.4 实际上与10 + (2 * 5) / (34 - 3.4) 不同。我对其进行了编辑以澄清。

标签: function kotlin lambda


【解决方案1】:

大括号 lambda 的真正好处在于,与所有最好的语言功能一样,它改变了您的思维方式。

您提供的示例同样用括号编写,我同意 IntelliJ 建议始终使用尾随形式是不必要的......

但是当我写这样的东西时:

with(someObject) {
    doSomething();
    doSomethingElse();
}

看起来就像我正在使用该语言的一个很酷的新功能,尽管我实际上只是在调用一个函数。

结果是人们开始认为他们可以编写函数来为语言添加东西,因为他们有点可以,这导致他们为使用他们的代码的人创造新的做事方式。

类型安全的构建器模式就是一个很好的例子。 Kotlin 语言的许多功能协同工作,因此,即使它只是调用函数和传递 lambda,它也为使用它的开发人员提供了全新的体验。

他们获得了一种全新的方式来实例化复杂对象,这种方式比旧方式更加自然,并且无需为此添加任何语言——所有的小构建块功能都可以用于许多其他方面东西。

【讨论】:

    【解决方案2】:

    根本没有实际的好处,只是一种约定。

    关于您所说的“保持标准”。你究竟从哪里得到“通常的方式”?我知道没有全球编程约定,只有特定于语言的约定,所以这种表示法在定义上是标准的。

    约定很重要,因为对于同样熟悉语法的人来说,它们使阅读代码的工作量大大减少。约定还反映了语言的使用。在 Kotlin 中,他们提倡一种非常实用的风格,大量使用 lambda 和内联函数,因此“括号外的 lambda”对于保持代码的简洁和明确是必要的。

    正如@Tenfour04 在 cmets 中所说,您的示例确实没有反映语法的预期用法。通常你有多行,即使你没有,模式也应该传达更多的东西。以measureTimeMillis函数为例:

    measureTimeMillis {
    
        askQuestion()
        comment()
        answerQuestion()
    }
    

    通过将 lambda 放在括号之外,可以立即清楚地看到函数的作用,即使对于非技术读者来说,这正是约定的用途。

    【讨论】:

      【解决方案3】:

      更接近您的示例。假设您需要转换一个数字数组并将所有正数平方。比较什么更容易阅读:

      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
              }
          }
      

      【讨论】:

      • 对我来说它是最重要的。也许它更适合那些对语言不太熟悉的人。括号让事情变得清晰。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-14
      • 1970-01-01
      • 1970-01-01
      • 2017-08-14
      • 1970-01-01
      • 2021-10-03
      相关资源
      最近更新 更多