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