Scala登陆.NET平台
为什么需要让Scala在.NET上运行?
Miguel:
总的来说有很多原因,这对开发者和企业两方面都非常具有吸引力。Scala是一个精确的并且具有高度生产力的编程语言。在.NET上使用Scala,开发者不仅能够更快速的开发出各种应用,而且能够在JVM和.NET这两个主流行业平台之间进行跨平台部署。
这对于开发者来说意味更多,因为只需要学习一种语言就可以在两种环境里创建应用。从企业的观点看,这也能够更好的利用珍稀资源,因为优秀的程序员可以轻松的跨越两个平台,减少了培训成本,增加了灵活性,降低了风险。.NET平台集成了多种语言,Scala的互操作性也很好,你可以使用现有的.NET库或现有的应用,不需要使用Scala重写。最终的效果是原先只能分别在.NET和JVM环境中使用的工具和应用都可以从一个环境移植到另一个环境,这是一个多赢的局面。从目前的情况看,Scala和.NET二者结合的非常好,对Scala开发者来说几乎不会察觉到是在.NET上运行。
现在就能在.NET上运行Scala程序了吗?
Miguel:答案很简单,是的,只是目前还有一点局限,但到今年秋天就会完全解决。
如果你想把正在JVM上运行的Scala程序移植到.NET上,需要做的只是使用Scala.NET编译器重新编译一遍,就可以在.NET上运行了。
现在碰到的主要局限就是Scala程序还不能使用.NET中那些用到CLR泛型的类库,比如.NET集合类。当然这只是一个小限制了,其他的功能全部可用,而且到今年秋天.NET泛型也能全部支持。
怎样在.NET上开发Scala程序呢?
Miguel:你可以直接在MS Visual Studio里开发。到今年秋天Visual Studio的Scala插件就能支持人们期望的各种基本功能了,具体地说,IDE、代码自动完成、代码浏览、断行、表达式和异常报告等等这些。
目前的Scala.NET编译器也已经非常强大了,它能够对自己进行编译,大概由十万行Scala代码组成。现在的插件还不支持代码自动完成和代码浏览,所以我有时还是会选择使用Eclipse或是Intellij在JVM上编写代码,然后在Visual Studio中做最终的调试。
你们是怎样做到的?
Miguel:主要需要克服的困难是Scala程序大量使用了Java JDK,而Java JDK在.NET环境中是不被支持的,所以Scala编译器必须要针对.NET而重新生成代码。
Java社区早已经开发出IKVM虚拟机,可以把Java程序转换成MSIL(Microsoft Intermediate Language,微软中间语言),此外还有一个.NET类库用来提供基本的JDK支持。IKVM是Jeroen Frijters很早以前就一直倡导的一个开源项目,也是为了遵循Java“一次编写,到处运行”的原则,IKVM存在很长时间了,作为开源项目非常成功,也有可靠的商业支持。IKVM类库是我们用来初始Scala.NET编译器的关键内容,而且给我们提供了将Scala类库搬上.NET的优良基础。
说来Scala.NET编译器的历史也很长了,但刚开始主要是集中在编译器的爱好者和黑客群体里,当时他们中有些人开发出了跨平台的编译器。在我进入的时候,跨平台编译器已经成型,但它还不能在.NET环境中启动自己。这意味着必须有一个能够自己编译自己的Scala.NET编译器,实际上这是一个先有鸡还是先有蛋的经典问题。
当时的跨平台编译器运行良好,但只能在JDK上运行。依靠大量的JDK API,这和目前的Scala应用一样。现在很多Scala开发者还是习惯使用JDK中的功能,即使这些功能在Scala SDK上也已经提供了。所以说我们虽然有了跨平台编译器,但缺乏方法,能够用.NET类库的功能自动替换那些JDK的功能。
IKVM编译器能够提取JVM字节码转换为.NET的Assembly类库。推进到字节码级别虽然是前进了一大步,但并没有给我们带来真正的开端,因为我们依旧没有摆脱对JDK的依靠。所以我们的任务就变成了创建一个前端处理器,能够修改Scala的源代码,将JDK直接替换为IKVM类库中的.NET相同功能,一种映射机制。
具体是怎样映射的呢?
Miguel:第一步是创建源代码级所需要的初始化转换。下一阶段是扩展Scala编译器来应用这些转换。Scala编译器是模块化的,支持各种插件,因此应用起来很方便,但并不是所有的编译器都能够那么灵活的做到。我们创建了一个新的Scala插件JDK2IKVM用来在批模式下完成源代码转换。得到的源代码引用IKVM类库,经过标准的编译器流程生成MSIL字节码。这就是我们现在的Scala.NET,能够自己编译自己的Scala编译器。实际操作中我们会反复进行多次编译/转换环节来完成全部的功能转换。
在后台我们使用了重构技术,这种技术也可以用于其它的平台移植,例如将Java.IO自动转换为Scala.IO。当然Scala.NET编译器本身也就是一个Scala应用,因此对于任何JVM上的Scala应用都会有效,这很好理解。
原始类型(Primitive Type)的兼容性怎样?
Miguel:.NET的CLR提供的原始类型是JVM类型的超集,从编译器的角度看来它们转换起来很容易。字符串和数值等等都能够完成转换,从我们开始测试起就没有发现什么困难情况。IKVM在IKVM社区已经使用了很多年了。
接下来准备做什么?