scala - 当 reflect.runtime.universe._ 存在时,为什么 reflect.runtime.universe.RuntimeClass 会推断为 Nothing?

标签 scala scala-reflect

我偶然发现了一个奇怪的情况,其中有 reflect.runtime.universe._进口原因reflect.runtime.universe.RuntimeClass推断它似乎在哪里Nothing会更合适。

考虑这个简单的方法和List :

import scala.reflect.ClassTag

def find[A : ClassTag](l: List[Any]): Option[A] =
    l collectFirst { case a: A => a }

val list = List(1, "a", false)

我可以使用它来查找 List 中的第一个元素某种类型的,并且效果很好,正如预期的那样。
scala> find[String](list)
res1: Option[String] = Some(a)

scala> find[Long](list)
res2: Option[Long] = None

如果我不提供类型参数,那么 A推断为 Nothing ,所以我得到 Option[Nothing] ,也符合预期。
scala> find(list)
res3: Option[Nothing] = None

但是,如果我 import scala.reflect.runtime.universe._并且再次不提供类型参数 A现在推断为 reflect.runtime.universe.RuntimeClass而不是 Nothing .
scala> find(list)
res4: Option[reflect.runtime.universe.RuntimeClass] = None
                ^ What?

这不是一个大问题,因为我几乎无法想象 find 的用例有多大。方法没有手动提供类型参数,但为什么会发生这种情况? ClassTag似乎是部分原因,因为再次删除它会导致 Nothing被推断(尽管由于删除而完全破坏了该方法)。这里发生了什么?

最佳答案

这看起来像是运行时 Universe 的一些完全意想不到的副作用。是内部设计的。
scala.reflect.runtime.universe有类型 scala.reflect.api.JavaUniverse .

通过导入它的所有成员,你导入了——尤其是——一堆隐含的 ClassTag scala.reflect.api.ImplicitTags 中定义的值由宇宙扩展的特性。
ImplicitTags trait 引入了大约 90 种不同的隐式 ClassTag值(value)观。其中,有这样一个:

implicit val RuntimeClassTag: ClassTag[RuntimeClass]

看起来编译器比其他人更喜欢它,因为它决定在推断任意 ClassTag[A] 时使用它.这是为什么?这是因为 RuntimeClassTagscala.reflect.api.JavaUniverse 中被覆盖子类中定义的隐式值优先于父类(super class)中定义的隐式值(如重载决议规则中的某处所指定 - SLS 6.26.3)

所以,总而言之,编译器推断出 RuntimeClass对于 AClassTag上下文绑定(bind),因为它在范围内看到了这个东西(由 Universe 上的通配符导入引入):
trait JavaUniverse extends Universe { self =>
  type RuntimeClass = java.lang.Class[_]
  implicit val RuntimeClassTag: ClassTag[RuntimeClass] = 
    ClassTag[RuntimeClass](classOf[RuntimeClass])
  ...
}

关于scala - 当 reflect.runtime.universe._ 存在时,为什么 reflect.runtime.universe.RuntimeClass 会推断为 Nothing?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30147880/

相关文章:

exception - Scala:无法捕获闭包内抛出的异常

scala - Scala中的嵌套注释列表

java - 如何在scala中动态输入cast Any?

scala - 在 Akka 中保留类型参数接收

scala - Scala中的存在与协方差

IntelliJ 的 Scala 风格指南格式化程序

scala - 如何在scala中获取reflect.runtime.universe.Type的类型参数?

Scala 解析器削减最后一个括号

scala - 像 $read 和 $iw 这样的奇怪名称在具体化表达式中做了什么?

java - Scala 使用可变参数构造函数扩展 Java 类