用于eta扩展的下划线用法

时间:2017-11-06 00:51:56

标签: scala

scala> val names = List("Peter", "Paul", "Mary")
names: List[String] = List(Peter, Paul, Mary)

scala> names.map(_.toUpperCase)
res12: List[String] = List(PETER, PAUL, MARY)

在这种情况下,下划线表示唯一的输入参数,它是名称的元素。该字符串隐式转换为StringOps,并调用toUpperCase。

然而,这不起作用:

scala> names.map(StringOps.toUpperCase _)
<console>:14: error: value toUpperCase is not a member of object scala.collection.immutable.StringOps
       names.map(StringOps.toUpperCase _)

我认为这种语法是我从toUpperCase方法获取函数的引用。

3 个答案:

答案 0 :(得分:2)

首先,将_.toUppercase转换为String的{​​{1}}没有隐式转化,因为StringOps属于toUppercase 1}}类型,不必要转换String

因此StringOps实际扩展为高阶函数:_.toUppercase

val a: String => String = (str: String) => str.toUpperCaseStringOps中定义了

Predef.scala 隐式转化,只有在使用augmentString时才会进行此转化方法,例如:StringOpsslicestripSuffix等,例如:

stripPrefix

答案 1 :(得分:1)

StringOps是一个类,因此要使用它的方法,你需要实例化一个实例:

names.map( x => (new StringOps(x)).toUpperCase )

或者

names.map( new StringOps(_) toUpperCase )

答案 2 :(得分:0)

StringOps是String类的包装类,这意味着它使用您正在使用的其他方法“丰富”此类。
如果要在字符串实例上调用方法,只需执行以下操作:

instanceName.methodName

这正是你在第一个例子中所做的。

但是,在您的第二个示例中,您正在执行以下操作:

methodName(instanceName)

toUpperCase不接受参数,它在字符串本身的实例上调用。