在scala lambda函数中使用_

时间:2011-10-06 11:22:14

标签: scala

任何人都可以解释我为什么能这样做:

a.mapValues(_.size)

而不是

a.mapValues(x => x.size)

但我做不到

a.groupBy(_)

而不是

a.groupBy(x => x)

2 个答案:

答案 0 :(得分:41)

当您编写a.groupBy(_)时,编译器会将其理解为匿名函数:

x => a.groupBy(x)

根据Scala规范§6.23,表达式中的下划线占位符将替换为匿名参数。所以:

  • _ + 1已扩展为x => x + 1
  • f(_)已扩展为x => f(x)
  • _不会自行展开(占位符不是任何表达式的一部分)。

表达式x => a.groupBy(x)会使编译器混淆,因为它无法推断出x的类型。如果a是某些类型E元素的集合,则编译器期望x(E) => K类型的函数,但无法推断类型K。 ..

答案 1 :(得分:16)

在这里看到它并不容易:

a.groupBy(_)

但是更容易看到这样的事情:

a.mkString("<", _, ">")

我正在部分应用方法/功能。我将它应用于一些参数(第一个和最后一个),并保留第二个参数未应用,所以我得到一个像这样的新函数:

x => a.mkString("<", x, ">")

第一个例子只是一个特殊情况,其中部分应用了唯一的参数。但是,在表达式上使用下划线时,它代表匿名函数中的位置参数。

a.mapValues(_.size)
a.mapValues(x => x.size)

很容易混淆,因为它们都会产生匿名功能。实际上,还有第三个下划线用于将方法转换为方法值(也是一个匿名函数),例如:

a.groupBy _