为什么Kotlin有lambdas /匿名函数的两种语法?

gyp*_*ve5 15 lambda anonymous-function kotlin

Kotlin有两种声明匿名函数的方法(也就是lambda).两种不同的语法是:

val lambda =  { input : String -> 
  "received ${string}"
}
Run Code Online (Sandbox Code Playgroud)

val anonymousFunction =  fun (input : String): String {
  return "received ${string}"
}
Run Code Online (Sandbox Code Playgroud)

我理解两者之间的区别(如本答案中所述),但我不明白的是为什么语言有两种不同的方式来声明同一件事.

对于另一个经验,是否在工作中有优化?匿名函数版本是否过于冗长?lambda版本的语法不支持返回类型吗?

yol*_*ole 19

关键原因是支持lambdas的回报.返回规则是return关键字从使用fun关键字声明的最近函数返回.在某些情况下,您希望return在封闭函数中返回一个代码块,因此您使用lambda:

fun processElements(list: List<Element>): Boolean {
     list.forEach { element ->
          if (!element.process()) return false   // returns from processElements()
     }
     return true
}
Run Code Online (Sandbox Code Playgroud)

在其他情况下,您希望从块返回,而不是从封闭函数返回.使用lambda时,从块返回需要return@label语法,这有点笨重:

fun processElements(list: List<Element>) {
     list.forEach { element ->
          if (!needToProcessElement(element)) return@forEach // returns from block
          element.process()
     }
}
Run Code Online (Sandbox Code Playgroud)

为了避免笨拙,我们提供了另一种语法 - 匿名函数 - 它允许您return直接使用从块返回:

fun processElements(list: List<Element>) {
    list.forEach(fun(element) { 
        if (!needToProcessElement(element)) return // returns from block
        element.process()
    })
}
Run Code Online (Sandbox Code Playgroud)

第二个原因是将返回类型声明放入lambda的语法中确实是不可能的,但这在实践中很少需要,所以它并不是特别重要.

  • 因此,如果我理解上述内容,那么 lambda 的标记返回语法被认为是不雅的,因此引入了匿名函数语法以允许块中未标记的早期返回。 (2认同)
  • 这不是历史上在1.0版本的Kotlin的演变过程中发生的情况,但这就是为什么我们在1.0中有两个语法. (2认同)
  • 我认为,一个更优雅的解决方案可能是只使用 lambda,并且始终将未标记的返回跳转回 lambda 的直接调用者。因此,如果您想进一步返回,则必须显式指定(“return@processElements”),因为从 labmda 的角度来看,这是一个具有更多“副作用”的语句(通常它应该只接受参数并返回结果),因此我认为这应该是需要明确标记的情况。未标记的 return 语句有两种语义可能是容易出错的根源。 (2认同)