Scala应用方法调用,因为括号与隐式参数冲突 [英] Scala apply method call as parentheses conflicts with implicit parameters
问题描述
Cay Horstmann的书不耐烦的斯卡拉"中有一条关于应用方法的注释:
There is a note in Cay Horstmann's book "Scala for the Impatient" about the apply method:
有时,()表示法与另一个Scala功能冲突: 隐式参数.例如,表达式
"Bonjour".sorted(3)
产生错误,因为可以有选择地调用已排序的方法 排序,但3无效.
Occasionally, the () notation conflicts with another Scala feature: implicit parameters. For example, the expression
"Bonjour".sorted(3)
yields an error because the sorted method can optionally be called with an ordering, but 3 is not a valid ordering.
解决方案是将"Bonjour".sorted
分配给变量,然后对其应用调用,例如:
The solution is to assign "Bonjour".sorted
to a variable and call apply on it, for example:
val result = "Bonjour".sorted
result(3)
或致电明确申请:
"Bonjour".sorted.apply(3)
但是为什么它不起作用并产生编译错误:
But why this doesn't work and produces a compile error:
("Bonjour".sorted)(3)
已排序的方法返回String
,可以将其隐式转换为StringOps
,并且括号用于包装字符串表达式.
为什么编译器不接受调用StringOps
的apply方法?
The sorted method returns a String
, which can be imlicitly converted to a StringOps
and parentheses are used to wrap the string expression.
Why compiler doesn't accept to call the apply method of a StringOps
?
推荐答案
您可以使用-Xprint:parser
来查看是否提前放弃了括号:
You can use -Xprint:parser
to see that the parens are discarded early:
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)
.因为它是一个应用程序,所以您不会获得隐式应用程序"转换.
The extra parens do nothing. The compiler just sees an application expr(args)
. Because it's an application, you don't get "implicit application" conversion.
在任何情况下,方法scaled
的含义取决于预期的类型.
In any case, the meaning of scaled
, a method, depends on the expected type.
我们期望额外的paren有所作为的原因是parens会覆盖运算符的优先级.但是(x)
只是x
.
The reason we expect the extra parens to make a difference is that parens override precedence of operators. But (x)
is just x
.
可能对此规格实际上是明确的:
Possibly the spec is actually clear about this:
e(args)
要求e
适用于args
.特别是,根据e
的参数类型对args进行类型检查.
e(args)
requires that e
be applicable to the args
. In particular, the args are typechecked according to the parameter types of e
.
e(args)
视为e.apply(args)
.
您希望隐式应用程序"插入隐式参数,但这仅在尚未应用e
时适用.或者,可以将(e)(args)
视为(e(_))(args)
,即(x => e(x))(arg)
.
You're hoping for "implicit application" to insert the implicit args, but that only applies when e
is not already applied. Or that (e)(args)
could be taken as (e(_))(args)
, that is, (x => e(x))(arg)
.
e
编写为e.apply(arg)
时,它不是像e(arg)
这样的应用程序,因此您将从诸如隐式应用程序之类的转换中受益.
When written as e.apply(arg)
, the e
is not an application like e(arg)
, so you benefit from conversions like implicit application.
这篇关于Scala应用方法调用,因为括号与隐式参数冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!