Scala 3 — Book

匿名函数

Language

匿名函数(也称为 lambda)是作为参数传递给高阶函数的代码块。 维基百科将 匿名函数 定义为“未绑定到标识符的函数定义”。

例如,给定这样的列表:

val ints = List(1, 2, 3)

您可以通过使用 Listmap 方法和自定义匿名函数将 ints 中的每个元素加倍来创建一个新列表:

val doubledInts = ints.map(_ * 2)    // List(2, 4, 6)

如注释所示,doubledInts 包含列表List(2, 4, 6)。 在该示例中,这部分代码是一个匿名函数:

_ * 2

这是“将给定元素乘以 2”的简写方式。

更长的形式

一旦你熟悉了 Scala,你就会一直使用这种形式来编写匿名函数,这些函数在函数的一个位置使用一个变量。 但如果你愿意,你也可以用更长的形式来写它们,所以除了写这段代码:

val doubledInts = ints.map(_ * 2)

您也可以使用以下形式编写它:

val doubledInts = ints.map((i: Int) => i * 2)
val doubledInts = ints.map((i) => i * 2)
val doubledInts = ints.map(i => i * 2)

所有这些行的含义完全相同:将 ints 中的每个元素加倍以创建一个新列表 doubledInts。 (稍后会解释每种形式的语法。)

如果您熟悉 Java,了解这些 map 示例与以下 Java 代码等价可能会有所帮助:

List<Integer> ints = List.of(1, 2, 3);
List<Integer> doubledInts = ints.stream()
                                .map(i -> i * 2)
                                .collect(Collectors.toList());

缩短匿名函数

当你想要明确时,你可以使用这个长格式编写一个匿名函数:

val doubledInts = ints.map((i: Int) => i * 2)

该表达式中的匿名函数是这样的:

(i: Int) => i * 2

如果您不熟悉这种语法,将 => 符号视为转换器会有所帮助,因为表达式使用 => 符号右侧的算法(在这种情况下,一个将 Int 加倍的表达式)把符号左侧的参数列表(名为 iInt 变量) 转换为新结果。

缩短该表达式

这种长形式可以缩短,如以下步骤所示。 首先,这是最长和最明确的形式:

val doubledInts = ints.map((i: Int) => i * 2)

因为 Scala 编译器可以从 ints 中的数据推断 i 是一个 Int,所以可以删除 Int 声明:

val doubledInts = ints.map((i) => i * 2)

因为只有一个参数,所以不需要在参数 i 周围的括号:

val doubledInts = ints.map(i => i * 2)

因为当参数在函数中只出现一次时,Scala 允许您使用 _ 符号而不是变量名,所以代码可以进一步简化:

val doubledInts = ints.map(_ * 2)

变得更短

在其他示例中,您可以进一步简化匿名函数。 例如,从最显式的形式开始,您可以使用带有 Listforeach 方法的匿名函数打印 ints 中的每个元素:

ints.foreach((i: Int) => println(i))

和以前一样,不需要 Int 声明,因为只有一个参数,所以不需要 i 周围的括号:

ints.foreach(i => println(i))

因为 i 在函数体中只使用一次,表达式可以进一步简化为 _ 符号:

ints.foreach(println(_))

最后,如果一个匿名函数由一个接受单个参数的方法调用组成,您不需要显式命名和指定参数,因此您最终可以只写方法的名称(此处为 println):

ints.foreach(println)

Contributors to this page: