gpt4 book ai didi

使用 TypeTag 对泛型类型进行 Scala 模式匹配会生成警告,而 ClassTag 不会?

转载 作者:行者123 更新时间:2023-12-04 22:44:11 29 4
gpt4 key购买 nike

我有两种非常相似的方法。唯一的区别是使用 ClassTagTypeTag :

def matchClass[A: ClassTag](v: Any) =
v match {
case a: A => "it's A"
case _ => "not A"
}

def matchType[A: TypeTag](v: Any) = ... // same code as matchClass

将显示 matchType 的编译警告,但不适用于 matchClass : abstract type pattern A is unchecked since it is eliminated by erasure case a: A
为什么会有警告?为什么它只显示 TypeTag而不是 ClassTag ?

最佳答案

您看不到 classTag 的警告因为该检查仅适用于那些:

scala> matchClass[Int]("aaa")
res82: String = not A

scala> matchClass[Int](5)
res83: String = it's A

并且不适用于 typeTag :
scala> matchType[Int](5)
res84: String = it's A

scala> matchType[Int]("aaa")
res85: String = it's A

原因是对于 classTags 上的模式匹配(当它看到隐式时)编译器会生成如下内容:
case a: A if classTag[A].runtimeClass.isInstance(a) => ...

没有办法得到 runtimeClass对于 TypeTag s 一般(考虑编译和运行时,请参阅更新以了解特定情况,仅允许在运行时提取它),这就是编译器不转换它们的原因。默认情况下,由于删除,模式匹配无法匹配泛型(多态)类型,因此默认情况下您可以看到该警告:
 scala> def matchGeneric[A](v: Any) =
| v match {
| case a: A => "it's A"
| case _ => "not A"
| }
<console>:28: warning: abstract type pattern A is unchecked since it is eliminated by erasure
case a: A => "it's A"
^
matchGeneric: [A](v: Any)String

更新:正如@Seth Tisue 提到的 when a tag comes from run-time universe (only)你可以为它获取一个运行时类(但你必须先创建一个镜像)。

引用:

根据 scaladocsClassTag本身:

The compiler tries to turn unchecked type tests in pattern matches into checked ones by wrapping a (_: T) type pattern as ct(_: T), where ct is the ClassTag[T] instance. Type tests necessary before calling other extractors are treated similarly. SomeExtractor(...) is turned into ct(SomeExtractor(...)) if T in SomeExtractor.unapply(x: T) is uncheckable, but we have an instance of ClassTag[T].


TypeTag scaladocs 和语言规范本身并未提及 TypeTags 的任何此类功能。

推测性解释

无法确定为什么要实现某些功能,因此任何猜测都是固执己见的(并且超出了 SO 范围,甚至与您的问题没有直接关系,而是回答 @Tom 的评论)。尽管如此(截至2.12)......

这可能是因为“ClassTags 只提供对一个类型的运行时类的访问”并且是 scala-library 的一部分。 (即使它们的包是 scala.reflect. ),而 TypeTags 是单独的(并且非常广泛的)反射 API 的一部分,因此意味着根据 universe 引用编译或运行时间他们在里面,所以为这些编写额外的检查(在合成期间!!)不仅会令人困惑(对用户而言),而且对语言开发人员来说也很困难:合成本身位于不同的 ( compiler) 模块和 [合成]不依赖于 reflection (仅 scala-library)因为模式匹配合成发生在早期的“patmat”阶段。此外,scala 规范(12.3.4.2 Variance)提到使用 ClassTag 对数组实例化进行综合调整,这(非常推测)可能意味着 ClassTag 与“语法糖”功能更加集成。

关于使用 TypeTag 对泛型类型进行 Scala 模式匹配会生成警告,而 ClassTag 不会?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34495711/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com