在Scala lambda函数中使用_

15 浏览
0 Comments

在Scala lambda函数中使用_

请问有人可以解释一下为什么我可以使用而不是 x.size)>,但我不能使用而不是 x)>吗?

0
0 Comments

在Scala中,当你写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...

谢谢。但是,为什么a.mapValues(_.size)不被解析为x => a.mapValues(x.size)

因为_.size是一个表达式。比较:List(1,2,3).map( 2 + twice(_) )List(1,2,3).map( twice(1+_) ),其中twice是一个将输入加倍的函数。

: 但是_也是一个表达式;它是一个表示在其上调用方法的值的表达式。而整个a.mapValues(_.size)也是一个表达式。包含这行代码的任何代码块也是一个表达式。我认为我对它的工作方式有一个直观的基本正确的理解,但是是否有一个明确的定义来解释Scala编译器会“走多远”的范围?也就是说,为什么它不仅仅将_转换为x => x,而是将_.size转换为x => s.size

我认为它在第一个方法应用之后停止。请记住,在Scala中,_.size_ + 1fn(_)等都被转换为方法应用。

: _将最内层“正确包含”它的Expr转换为一个函数。这里的“正确包含”意味着“包含_并且还包含至少一个其他单词或符号”。这将排除_本身成为身份函数的可能性。Expr是一种特定类型的表达式,这是一种语法上的区别。特别是函数调用的每个参数以及括号中的几乎任何其他表达式都是Expr

0
0 Comments

Scala中lambda函数中使用下划线(_)的原因和解决方法

在Scala中,lambda函数是一种匿名函数,可以通过使用下划线(_)来部分应用方法或函数。下划线的使用方式有三种,分别是用于部分应用方法的参数、用于匿名函数的位置参数和用于将方法转换为方法值。

在第一个例子中,使用下划线对表达式进行部分应用,它代表的是位置参数。例如,a.groupBy(_)中的下划线代表着将groupBy方法应用到参数a上,但是第二个参数未应用。

在第二个例子中,使用下划线对mkString方法进行部分应用,同样代表位置参数。例如,a.mkString("<", _, ">")中的下划线代表将"<"这个参数应用到mkString方法的第一个位置参数上,但第二个参数和第三个参数未应用。

当使用下划线作为表达式时,它代表位置参数,这很容易引起混淆。例如,a.mapValues(_.size)a.mapValues(x => x.size)都会生成匿名函数,但是它们实际上是不同的。

此外,还有一个特殊情况,下划线用于将方法转换为方法值,也是一种匿名函数。例如,a.groupBy _将groupBy方法转换为方法值。

因此,在Scala中,下划线的使用方式可能会引起混淆,特别是在匿名函数中使用。为了避免混淆,可以明确指定参数,或者使用完整的匿名函数定义来替代使用下划线的部分应用方法。

0