您可以使用-Xprint:parser
来查看括号是否被提前丢弃:
scala> implicit class x(val s: String) { def scaled(implicit i: Int) = s * i }
defined class x
scala> "hi".scaled(5)
res0: String = hihihihihi
scala> { implicit val n: Int = 5 ; "hi".scaled }
res1: String = hihihihihi
scala> "hi".scaled(5)(3)
res2: Char = i
scala> { implicit val n: Int = 5 ; ("hi".scaled)(3) }
res3: String = hihihi
scala> :se -Xprint:parser
scala> { implicit val n: Int = 5 ; ("hi".scaled)(3) }
[[syntax trees at end of parser]] // <console>
package $line8 {
object $read extends scala.AnyRef {
def <init>() = {
super.<init>();
()
};
object $iw extends scala.AnyRef {
def <init>() = {
super.<init>();
()
};
import $line3.$read.$iw.$iw.x;
object $iw extends scala.AnyRef {
def <init>() = {
super.<init>();
()
};
val res4 = {
implicit val n: Int = 5;
"hi".scaled(3)
}
}
}
}
}
res4: String = hihihi
scala>
额外的括号什么都不做。编译器只看到一个应用程序expr(args)
。因为它是一个应用程序,所以您不会获得“隐式应用程序”转换。
在任何情况下,方法的含义scaled
取决于预期的类型。
我们期望额外的括号会有所作为的原因是括号会覆盖运算符的优先级。但(x)
只是x
。
可能规范实际上对此很清楚:
e(args)
要求e
适用于args
. 特别是,根据 的参数类型对 args 进行类型检查e
。
e(args)
被认为e.apply(args)
是e
一个值,但是scaled
是一个方法。
您希望“隐式应用程序”插入隐式参数,但这仅适用于e
尚未应用的情况。或者(e)(args)
可以(e(_))(args)
认为是 ,即(x => e(x))(arg)
。
当写成 时e.apply(arg)
,e
不是类似的应用程序e(arg)
,因此您可以从隐式应用程序等转换中受益。