第2世界
发布于 2023-04-17 / 27 阅读 / 0 评论 / 0 点赞

kotlin 函数名后面为什么是大括号

看 kotlin 代码的时候,经常有个疑惑就是明明是个函数后面为什么不是 () 而是 {}。百度搜索很久不知道该搜索什么东西,最后找到了这篇文章:https://zhuanlan.zhihu.com/p/78571521 。下面是其中一段摘录,解释了其中的奥秘。

Lambda 表达式的语法

{x: Int, y: Int -> x + y}

可以把 lambda 表达式存储在一个变量中,把这个变量当做普通函数对待:

val sum = {x: Int, y: Int -> x + y}
println(sum(1, 2))

也可以直接调用 lambda 表达式:

{ println(42) }()

但这样语法毫无可读性,也没意义,如果确定需要把一小段代码封闭在一个代码块中,可以使用库函数 run 来执行传给它的 lambda:

run{ println(42) }

因此,上述的 maxBy 函数在不用简明语法的情况下可这么写:

people.maxBy({ p: Person -> p.age} )

Kotlin 有这样的一个约定:如果 lambda 表达式是函数调用的最后一个实参,它可以放到括号的外边。

people.maxBy(){ p: Person -> p.age}

当 lambda 是函数唯一实参时,还可以去掉代码中的空括号对:

people.maxBy{ p: Person -> p.age}

如果 lambda 参数的类型可以被推导出来,你就不需要显示地指定它:

people.maxBy{ p -> p.age}

可使用默认参数名称 it 命名参数。如果当前上下文期望的是只有一个参数的 lambda 且这个参数的类型可以推导出来,就会生成这个名称:

people.maxBy{ it.age}

如果使用变量存储 lambda,那么久没有可以推断出参数类型的上下文,所以你必须显示地指定参数类型:

val getAge = {p: Person -> p.age}
people.maxBy(getAge)

此外,如果 lambda 表达式由多个语句构成,那么最后一个表达式就是 lambda 的结果:

val sum = { x: Int, y: Int ->
  println("Computing the sum of $x and $y...")
  x + y
}
println(sum(1, 2))


评论