Scala:隐式参数解析优先级 [英] Scala: Implicit parameter resolution precedence

查看:104
本文介绍了Scala:隐式参数解析优先级的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们仅对本地作用域进行隐式参数查找:

Suppose we have implicit parameter lookup concerning only local scopes:

trait CanFoo[A] {
  def foos(x: A): String
}

object Def {
  implicit object ImportIntFoo extends CanFoo[Int] {
    def foos(x: Int) = "ImportIntFoo:" + x.toString
  }
}

object Main {
  def test(): String = {
    implicit object LocalIntFoo extends CanFoo[Int] {
      def foos(x: Int) = "LocalIntFoo:" + x.toString
    }
    import Def._

    foo(1)
  }

  def foo[A:CanFoo](x: A): String = implicitly[CanFoo[A]].foos(x)
}

在上面的代码中,LocalIntFoo胜过ImportedIntFoo. 有人可以使用静态重载解析规则(第6.26.3节)"解释它被认为是更具体"吗?

In the above code, LocalIntFoo wins over ImportedIntFoo. Could someone explain how it's considered more specific using "the rules of static overloading resolution (§6.26.3)"?

修改:

名称绑定优先级是一个令人信服的参数,但是有几个问题尚未解决. 首先,Scala语言参考说:

The name binding precedence is a compelling argument, but there are several issues unresolved. First, Scala Language Reference says:

如果有多个与隐式参数类型匹配的合格参数,则将使用静态重载解析规则(第6.26.3节)选择一个最具体的参数.

If there are several eligible arguments which match the implicit parameter’s type, a most specific one will be chosen using the rules of static overloading resolution (§6.26.3).

第二,名称绑定优先级是在范围内有多个名为x的变量/方法/对象的情况下,将已知标识符x解析为特定成员pkg.A.B.x. ImportIntFooLocalIntFoo的命名不同.

Second, name binding precedence is about resolving a known identifier x to a particular member pkg.A.B.x in case there are several variable/method/object named x in the scope. ImportIntFoo and LocalIntFoo are not named the same.

第三,我可以证明名称绑定优先级 并没有发挥作用,如下所示:

Third, I can show that name binding precedence alone is not in play as follows:

trait CanFoo[A] {
  def foos(x: A): String
}

object Def {
  implicit object ImportIntFoo extends CanFoo[Int] {
    def foos(x: Int) = "ImportIntFoo:" + x.toString
  }
}

object Main {
  def test(): String = {
    implicit object LocalAnyFoo extends CanFoo[Any] {
      def foos(x: Any) = "LocalAnyFoo:" + x.toString
    }

    // implicit object LocalIntFoo extends CanFoo[Int] {
    //   def foos(x: Int) = "LocalIntFoo:" + x.toString
    // }
    import Def._

    foo(1)
  }

  def foo[A:CanFoo](x: A): String = implicitly[CanFoo[A]].foos(x)
}

println(Main.test)

将此内容放入test.scala并运行scala test.scala,它会打印出ImportIntFoo:1. 这是因为静态重载解决方案(第6.26.3节)说,更具体的类型胜出. 如果我们假装所有合格的隐式值都被命名为相同,则LocalAnyFoo应该具有掩码的ImportIntFoo.

Put this in test.scala and run scala test.scala, and it prints out ImportIntFoo:1. This is because static overloading resolution (§6.26.3) says more specific type wins. If we are pretending that all eligible implicit values are named the same, LocalAnyFoo should have masked ImportIntFoo.

相关:

这是隐式参数解析的精彩摘要,但引用了Josh的nescala表示形式,而不是规范.他的讲话促使我对此进行研究.

This is a great summary of implicit parameter resolution, but it quotes Josh's nescala presentation instead of the spec. His talk is what motivated me to look into this.

编译器实现

推荐答案

我以博客文章 更新:此外,马丁·奥德斯基(Martin Odersky)在上一篇文章中的评论显示,Scala 2.9.1赢得LocalIntFoo赢得ImportedIntFoo的行为实际上是一个错误.再次参见隐式参数优先级.

Update: Furthermore, the comments from Martin Odersky in the above post revealed that the Scala 2.9.1's behavior of LocalIntFoo winning over ImportedIntFoo is in fact a bug. See implicit parameter precedence again.

  • 1)通过本地声明,导入,外部作用域,继承,可无前缀访问的包对象对当前调用范围可见的隐式对象.
  • 2)隐式作用域,其中包含与我们搜索的隐式类型有某种关系的各种伴随对象和包对象(即,该类型的包对象,该类型的伴随对象本身,类型构造函数(如果有的话),参数(如果有的话)以及它的超类型和超特性.)
  • 1) implicits visible to current invocation scope via local declaration, imports, outer scope, inheritance, package object that are accessible without prefix.
  • 2) implicit scope, which contains all sort of companion objects and package object that bear some relation to the implicit's type which we search for (i.e. package object of the type, companion object of the type itself, of its type constructor if any, of its parameters if any, and also of its supertype and supertraits).

如果在任一阶段我们发现一个以上的隐式静态静态重载规则都可以用来解决该问题.

If at either stage we find more than one implicit, static overloading rule is used to resolve it.

更新2 :当我向Josh询问没有进口税的隐含物品时,他向我解释说,他指的是隐含物品的名称绑定规则,它们的名称完全相同

Update 2: When I asked Josh about Implicits without Import Tax, he explained to me that he was referring to name binding rules for implicits that are named exactly the same.

这篇关于Scala:隐式参数解析优先级的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆