繁体   English   中英

Scala应用方法调用作为括号与隐式参数冲突

[英]Scala apply method call as parentheses conflicts with implicit parameters

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方法?

您可以使用-Xprint:parser查看早期丢弃的parens:

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> 

额外的parens什么都不做。 编译器只看到一个应用程序expr(args) 因为它是一个应用程序,所以不会进行“隐式应用程序”转换。

在任何情况下, scaled的含义,方法,取决于预期的类型。

我们期望额外的parens有所作为的原因是parens覆盖运算符的优先级。 但是(x)只是x

可能规范实际上是明确的:

e(args)要求e适用于args 特别是,根据e的参数类型对args进行类型检查。

如果e是值,则e(args)被视为e.apply(args) ,但是scaled是一种方法。

您希望“隐式应用程序”插入隐式args,但这仅适用于尚未应用e情况。 或者(e)(args)可以取为(e(_))(args) ,即(x => e(x))(arg)

当写为e.apply(arg)e不是像e(arg)这样的应用程序,因此您可以从隐式应用程序等转换中受益。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM