Scala(至少在JVM上)使用类型擦除来实现 Java 兼容性。这个功能被广泛 持有 吸。_ 在 JVM 上解决这个问题会很困难。
与 JVM 的情况相比,.NET 支持具体化的泛型。Scala 的 .NET 实现是否使用它们?如果不是,可以吗,否则使用具体化会导致什么问题?
Scala(至少在JVM上)使用类型擦除来实现 Java 兼容性。这个功能被广泛 持有 吸。_ 在 JVM 上解决这个问题会很困难。
与 JVM 的情况相比,.NET 支持具体化的泛型。Scala 的 .NET 实现是否使用它们?如果不是,可以吗,否则使用具体化会导致什么问题?
它正在进行中,小心不要破坏 JVM 和 .NET 之间的 Scala 语义。
早在 2011 年,我就在 scala-tools 邮件列表上问过这个问题,Miguel Garcia 给出了答案,他在其中概述了大局:
一些报价:
(1) Scala.Net 预览版目前做了什么。正如您所注意到的,擦除阶段也作为管道的一部分运行。这是预览版的一个“功能”,一个必须包含的“功能”,因为还没有对 CLR 泛型的支持(更多内容见下文)。然而,在 Scala.Net 中运行 JVM 风格的擦除有一个很大的优势:所有依赖 Scala 库的 Scala 程序都可以在 .Net 上编译,而不是等待 CLR Generics 准备好。那些依赖于 Java JDK 的程序也可以被编译,这取决于 IKVM 对相关 JDK API 的支持 [1]。
(2) Scala.Net 中对 CLR 泛型的支持。支持它的主要动机是获得与现有程序集的互操作性。在获得这种互操作性时,将注意不要脱离 Scala 语义。换句话说,任何有效的 Scala 程序都将在 JVM 和 .NET 上运行并产生相同的结果。这将我们带到了正在进行的工作 [2]。初始原型仅处理 Scala 的 C# 子集。所以现在我要解决剩下的问题。这比最初预期的要多,但覆盖整个语言很重要。
关于与 .NET 程序集的互操作的更多评论,特别是本机问题。是的,CLR 程序集可以使用“native int”(不同 CPU 上的不同大小)、由 .dll 导出的 C 函数的 P/Invoke 等来表达。Scala.Net 不打算做这种低级的诡计。感兴趣的程序集互操作性处于“公共语言规范”级别,即通常从任何 C#、VB.NET 等编译器获得的内容(“通常”,即除非使用“[DllImport]”属性和相关的 C++-isms )。
引用 CLI 规范:
--- 开始引用 --- 公共语言规范 (CLS) -- CLS 是语言设计者和框架(即类库)设计者之间的协议。它指定了 CTS(通用类型系统)的一个子集和一组使用约定。语言通过至少实现属于 CLS 的 CTS 的那些部分,为其用户提供访问框架的最大能力。类似地,如果框架的公开导出方面(例如,类、接口、方法和字段)仅使用属于 CLS 的一部分并遵守 CLS 约定的类型,那么框架将得到最广泛的使用。--- 结束报价 ---
查看整个线程:
https://groups.google.com/forum/?fromgroups#!topic/scala-tools/JDjstK1_uvM
从这个问题的答案中,您可以认为在 VM 中保留泛型可能根本不是优势,因为它仍然会决定可以表示什么以及类型之间的关系是什么。(更深入的,请访问 Ola Bini 的原始博客)。
其他示例:
擦除似乎不仅对向后兼容有用,而且因为动态类型语言所提倡的完整运行时类型信息是有代价的。.NET CLR 泛型的设计通过代码专业化解决了这一成本问题。上述案例应该清楚地表明它何时是擦除以及何时应归咎于特定缺陷的语言。
网络是,如果 JVM 已经具体化了泛型(没有类型擦除),就不可能实现 Scala 的类型系统...... Scala 的类型系统比 Java 的更复杂,如果 JVM 有基于 Java 泛型的泛型,在 Scala 中我们仍然会遇到问题。另一方面,类型擦除允许编译器实现复杂的类型系统,即使所有类型信息在运行时都不可用。
据我所知,Scala 的 .NET 后端远远落后于当前的 JVM 实现,也不支持 .NET 的具体化泛型。
Scala 2.10 甚至在从实际虚拟机模型中抽象类型信息的方向上更进一步。Martin Odersky 在一个演示文稿中展示了新的反射/具体化交互,例如嵌入在这个条目中(从 42'18" 开始)。
我相信您将能够使用类型标签(替换清单)来克服模式匹配和擦除的问题。这个邮件列表线程有一点,但我不知道它在多大程度上有效或无效。
(纯属猜测:)对于类型信息比 JVM 更少的平台的后端,寻求更多的抽象可能会有所帮助,例如对 JavaScript 的假设编译。