In Scala 3: Why runtime pattern matching can't work reliably on duck type using JVM reflection?

huangapple go评论55阅读模式
英文:

In Scala 3: Why runtime pattern matching can't work reliably on duck type using JVM reflection?

问题

考虑以下示例:

object MatchDuckType {

trait Sup
class Sub1() extends Sup {
def v1: String = "a"
}

def example(v: Any) = {

v match {

  case _: Sup { def v1: String } => println(1)
  case _ => println(2)
}

}

def main(args: Array[String]): Unit = {
example(Sub1())
example(1)
}
}


编译器给出了以下错误:

MatchDuckType.scala:16:12: xxx.MatchDuckType.Sup{v1: String}的类型测试无法在运行时检查


这个声明显然是错误的,因为`Sup { def v1: String }`可以通过Java运行时反射轻松检查(首先获取术语的类,然后获取其方法签名)。为什么警告仍然存在?这是编译器的一个错误吗?
英文:

Considering the following example:

object MatchDuckType {

  trait Sup
  class Sub1() extends Sup {
    def v1: String = "a"
  }

  def example(v: Any) = {

    v match {

      case _: Sup { def v1: String } => println(1)
      case _ => println(2)
    }
  }

  def main(args: Array[String]): Unit = {
    example(Sub1())
    example(1)
  }
}

The compiler gave the following error:

MatchDuckType.scala:16:12: the type test for xxx.MatchDuckType.Sup{v1: String} cannot be checked at runtime

This statement is clearly wrong, as Sup { def v1: String } can be easily checked by Java runtime reflection (by first getting the class of the term, then getting its method signatures). Why does the warning still exist? Is it a bug in compiler?

答案1

得分: 4

这不起作用不仅仅是一个“bug”;在语言中包括这样的功能需要大量的设计、规范和实现工作。

您希望的这个功能在Scala 2和Scala 3中都不存在。

我找到了一个关于这个功能的请求,可以追溯到2007年(!),但它从未引起太多关注:https://github.com/scala/bug/issues/329

即使这个功能存在,它也将是特定于平台的,范围有限:它只能在JVM上工作,而不能在JS或本机上工作,它只能用于可以在字节码中忠实表示的细化类型的子集。这排除了很多Scala类型系统的内容。

(至少没有TypeTag,但TypeTag仅适用于Scala 2;关于基于TypeTag的匹配的功能请求是https://github.com/scala/bug/issues/6517。在Scala 3上下文中,考虑尝试使用匹配类型吗?)

至于您关于解糖的评论,模式匹配会解糖为isInstanceOf,而isInstanceOf的行为是相同的,所以这实际上不是关于模式匹配本身,而是关于类型测试。

英文:

That this doesn't work isn't merely a "bug"; including such a thing in the language would require substantial design, specification, and implementation work.

The feature you were hoping for doesn't exist in either Scala 2 or Scala 3.

I found a feature request for this dating back to 2007 (!), but it never attracted much attention: https://github.com/scala/bug/issues/329

Even if the feature did exist, the feature would be platform-specific and limited in scope: it would only work on the JVM, not on JS or Native, and it would only work for the subset of refinement types that can be faithfully be represented in bytecode. That leaves out a lot of the Scala type system.

(At least without TypeTag, but TypeTag is Scala 2-only; the feature request on TypeTag-based matching is https://github.com/scala/bug/issues/6517 . In a Scala 3 context, consider trying to use match types instead?)

As for your remark about desugaring, pattern matches desugar to isInstanceOf, and the behavior of isInstanceOf is the same, so this isn't really about pattern matching per se, it's about type tests.

huangapple
  • 本文由 发表于 2023年2月14日 04:02:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/75440665.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定