加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala:隐式参数分辨率优先

发布时间:2020-12-16 09:19:21 所属栏目:安全 来源:网络整理
导读:假设我们只有局部范围的隐式参数查找: 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 o
假设我们只有局部范围的隐式参数查找:

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)”来解释它是如何被更具体化的?

编辑:

名称绑定优先级是一个引人注目的论据,但有几个问题尚未解决.
首先,Scala语言参考指出:

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解析为特定成员pkg.A.B.x,以防在范围中有几个名为x的变量/方法/对象. ImportIntFoo和LocalIntFoo没有命名相同.

第三,我可以看出,这个名字绑定的优先级并不如下:

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.

有关:

> Where does Scala look for implicits?

这是隐式参数解析的一个很好的总结,但它引用了Josh的nescala演示文稿而不是规范.他的演讲是促使我研究的.

编译器实现

> rankImplicits

解决方法

我以博客文章 revisiting implicits without import tax的形式写了自己的答案.

更新:此外,Martin Odersky在上述帖子中的评论显示,Scala 2.9.1的LocalIntFoo胜过ImportedIntFoo的行为实际上是一个错误.见implicit parameter precedence again.

> 1)通过本地声明,导入,外部范围,继承,无前缀访问的程序包对象,对当前调用范围可见的隐含.
> 2)隐含范围,它包含与我们搜索的隐式类型有一些关系的所有类型的伴随对象和包对象(即类型的包对象,类型本身的配对对象,其类型构造函数(如果有的话)的参数,如果有的话,以及它的超类型和超级词).

如果在任一阶段我们发现多个隐式静态重载规则用于解决它.

更新2:当我问乔希关于没有进口税的申请时,他向我解释说,他指的是名称绑定规则,这些规则被命名完全一样.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读