将Scala转换为golang是否可行/有用?

时间:2016-05-26 21:36:29

标签: scala go scala-native

最近发布了Scala native,但他们使用的垃圾收集器(目前)非常rudimentary,因此不适合严肃使用。

所以我想知道:为什么不只是将Scala转换为Go (一个scala.js)?它将是一个快速,可移植的运行时。他们的GC越来越好了。更不用说一个伟大的并发模型的继承:渠道和goroutines。

  • 那么为什么scala-native选择使用LLVM这么低级呢?
  • golang transpiler会有什么收获?

1 个答案:

答案 0 :(得分:18)

有两种语言是编译器的良好目标:

  1. 语义与源语言的语义非常匹配的语言。
  2. 具有非常低级且因此非常一般语义的语言(或者有人可能会说:根本没有语义)。
  3. #1的示例包括:编译ECMAScript 2015 to ECMAScript 5(大多数语言添加专门设计为现有功能的语法糖,你只需要去除它们),编译CoffeeScript to ECMAScript,编译TypeScript to ECMAScript (基本上,在类型检查之后,只需删除类型并完成),编译Java to JVM byte code,编译C♯ to CLI CIL bytecode,编译Python to CPython bytecode,编译Python to PyPy bytecode,编译{{3} },编译Ruby to YARV bytecode,编译Ruby to Rubinius bytecode

    #2的示例包括:通用CPU的机器代码(ECMAScript to SpiderMonkey bytecode),RISC even more soC--

    编译Scala to Go不适合两者。他们的语义非常不同。

    您需要使用具有强大低级语义的语言作为目标语言,以便您可以构建您自己的语义,或者您需要一种语言紧密匹配语义,以便您可以映射自己的语义转换为目标语言。

    事实上,即使JVM字节码已经高级了!它具有诸如与Scala的特征之类的构造不匹配的类的构造,因此必须对类和接口中的特征进行相当复杂的编码。同样,在invokedynamic之前,实际上几乎不可能在JVM字节码中表示结构类型的动态调度。 Scala编译器不得不求助于反射,换句话说,故意踩到外部的JVM字节码的语义(这导致结构类型上的方法调度与其他方法调度相比,性能开销很大)类类型,即使两者都是完全相同的东西)。

    正确的尾调用是另一个例子:我们希望在Scala中使用它们,但是因为JVM字节码不足以在没有非常复杂映射的情况下表达它们(基本上,你必须放弃使用完全调用JVM的调用堆栈并管理自己的堆栈,这会破坏性能和Java互操作性),决定不使用它们。

    Go有一些相同的问题:为了实现Scala的表达式非本地控制流构造,例如异常或线程,我们需要一个同样表达的非本地控制流构造来映射。对于典型的目标语言,这个"富有表现力的非本地控制流构造"是延续还是尊敬的GOTO。 Go LLVM,但故意限制在其非本地化"中。对于编写人类的代码,限制GOTO的表达能力是一件好事,但对于编译器目标语言而言,并非如此。

    很有可能使用goroutines和channel来装配强大的控制流,但现在我们已经离开了将Scala语义映射到Go语义的舒适范围,并开始在Go上构建Scala高级语义没有为这种用法设计的高级语义。 Goroutines并未被设计为一般控制流构造,以构建其他类型的控制流。那不是他们擅长的东西!

      

    那么为什么scala-native选择使用LLVM这么低级呢?

    因为这正是LLVM的设计目标并且擅长。

      

    Golang编辑器有什么特色?

    两种语言的语义对于直接映射来说太不同了,而且Go的语义不是为在上面构建不同的语言语义而设计的。

      

    他们的GC越来越好了

    Scala-native也可以。据我所知,目前使用Boehm-Dehmers-Weiser的选择基本上就是懒惰:它在那里,它有效,你可以把它放到你的代码中它只是做它的事情

    请注意,更改GC为GOTO。还有其他GC被设计为drop-ins而不是紧密耦合到主机VM的对象布局。例如。 IBM目前正在将其高性能JVM J9重新构建为一组松散耦合,可独立重用的运行时构建块"组件并在许可的开源许可下发布它们。

    该项目名为under discussion"Eclipse OMR"),它已经可以投入生产了:IBM J9的Java 8实现完全由OMR组件构建。有一个source on GitHub项目,它演示了如何轻松地将组件集成到现有的语言运行库中,因为组件本身不假定语言语义,也没有特定的内存或对象布局。 Ruby + OMR交换了GC,并在10000多行中添加了JIT和一个分析器时钟。它不是生产就绪的,但它可以启动和运行Rails。他们也有类似的CPython项目(尚未公开)。

      

    为什么不将Scala转换为Go(scala.js)?

    请注意,Scala.JS有很多我上面提到的相同问题。但他们无论如何都在这样做,因为收益是巨大的:你可以访问这个星球上的每个网络浏览器。对于假设的Scala.go,没有可比的收益。

    这就是为什么有一些举措可以将低级语义添加到浏览器中,例如commitasm.js,这正是因为将高级语言编译为另一种高级语言总是有这个"语义差距"你需要克服。

    事实上,请注意,即使对于专门设计为特定语言的编译目标的低级语言,您仍然可能遇到麻烦。例如。 Java有泛型,JVM字节码没有。 Java有内部类,JVM字节码没有。 Java有匿名类,JVM字节码没有。所有这些都必须以某种方式进行编码,特别是泛型的编码(或者说非编码)已经引起了各种各样的痛苦。