Cay Horstmann的书“Scala for the Impatient”中有关于apply方法的注释:
偶尔,()表示法与另一个Scala功能冲突:隐式参数 . 例如,表达式“Bonjour”.sorted(3)会产生错误,因为可以选择使用排序调用排序方法,但3不是有效排序 .
解决方案是将 "Bonjour".sorted
分配给变量并对其调用apply,例如:
val result = "Bonjour".sorted
result(3)
或明确致电申请:
"Bonjour".sorted.apply(3)
但为什么这不起作用并产生编译错误:
("Bonjour".sorted)(3)
sorted方法返回 String
,可以将其明确转换为 StringOps
,括号用于包装字符串表达式 . 为什么编译器不接受调用 StringOps
的apply方法?
1 回答
您可以使用
-Xprint:parser
查看早期丢弃的parens:额外的parens什么都不做 . 编译器只看到一个应用程序
expr(args)
. 因为它's an application, you don'得到"implicit application"转换 .在任何情况下,方法
scaled
的含义取决于预期的类型 .我们期望额外的parens有所作为的原因是parens覆盖运算符的优先级 . 但
(x)
只是x
.可能规范实际上是明确的:
e(args)
要求e
适用于args
. 特别是,根据e
的参数类型对args进行了类型检查 .如果
e
是一个值,e(args)
将被视为e.apply(args)
,但scaled
是一种方法 .您希望"implicit application"插入隐式参数,但这仅适用于尚未应用
e
的情况 . 或者(e)(args)
可以被视为(e(_))(args)
,即(x => e(x))(arg)
.当写为
e.apply(arg)
时,e
不是像e(arg)
这样的应用程序,因此您可以从隐式应用程序等转换中受益 .