JSweet是否可以有效移植Java库以供在交叉构建的Scala.js项目中使用?

时间:2018-06-26 02:14:21

标签: scala scala.js scalajs-bundler jsweet

在寻找使Scala.js cross-built项目的JavaScript和JVM端都可以访问Java库的方法时,请考虑以下实验:

想象一下,一个Scala.js项目需要高级矩阵数学功能,例如Singular Value Decomposition。尽管JavaScript世界有Numeric.js,而JVM世界有很多选择,JAMA尤其如此,但在提出此问题时,尚无跨版本的Scala.js解决方案。

我们有什么选择?

  1. 重新编写或移植用于Scala.js的矩阵库。
  2. 将Numeric.js外观和JAMA包装到一个通用的Scala.js接口中。
  3. 编写Numeric.js的外观,然后使用Nashorn进行编译以获取JVM支持。
  4. 使用JSweet将JAMA转换为JavaScript,并构建合适的Scala.js外观。

此问题反映了选项4。

重新整理JAMA for the JSweet transpiler,将已转译的JavaScript作为CommonJS module through npm发布并为CommonJS模块编写Scala.js facades之后,Scala代码现在可以访问JVM端的Jama和端口在JS端。

不幸的是,JVM端的核心数据结构具有Scala语法类型:double [] [],Array [Array [Double]],但是JSweet将其转换为JavaScript数组类型js.Array [js.Array] [Double]]使用Scala.js语法。

现在,从Scala.js交叉构建的角度来看,存在两个名称相同,功能相同但完全不同且独立的库。

通过Scala语法,我们可以这样在JS端构造3D身份矩阵:

new Matrix(
  js.Array[js.Array[Double]](
    new js.Array[Double](1.0, 0.0, 0.0),
    new js.Array[Double](0.0, 1.0, 0.0),
    new js.Array[Double](0.0, 0.0, 1.0)
   )
 )

在JVM方面,我们编写:

new Matrix(
  Array[Array[Double]](
    new Array[Double](1.0, 0.0, 0.0),
    new Array[Double](0.0, 1.0, 0.0),
    new Array[Double](0.0, 0.0, 1.0)
  )
)

我们如何统一这两个实现?

是否有将js.Array和Array等同的技巧?

您是否会提出一种完全不同的方法,以使交叉构建的Scala.js项目可以访问Java库?

2 个答案:

答案 0 :(得分:2)

让我从一个简单的问题开始:

  

是否有将js.Array和Array等同的技巧?

不,没有这样的“把戏”。这些数据结构 根本不同。 js.Array的长度是可变的,可以使用其他属性进行修补。 Array是Java的固定长度数组。如果有什么方法可以等同于它们,Scala.js会为您做到这一点,就像Doublenumber一样。

一种相对简单的统一API的方法是在Scala.js代码中重建JAMA的 API ,其中每个类都是来自JSweet编译库的外层JS类的包装。 。这使得JAMA的Scala级API在Scala / JVM和Scala.js之间完全等效。复制API确实需要一定数量的代码编写,但至少不需要重写方法主体。

一种完全不同的方法,非常激进并且需要大量的工时,因此JSweet编译器将分叉出Scala.js IR(.sjsir)文件而不是.js文件。这样,您可以将JAMA的JSweet生成的.sjsir文件与应用程序的Scala.js生成的.sjsir文件链接在一起。因为Scala.js优化器将能够跨应用程序/库边界进行优化,所以这将提供最佳性能。

答案 1 :(得分:0)

将Java库移植到Scala.js的方法:

  1. 获取Java源代码。
  2. 剥离IO和其他JSweet不兼容的功能。
  3. 使用JSweet作为Node.js模块对其进行编译。
  4. 手动滚动package.json文件并在npm上发布JSweet Transpiler输出。
  5. 将ScalaJS-bundler添加到交叉编译的Scala.js项目中;包括第五步中的CommonJS模块。
  6. 将Java版本包含在build.sbt的JVM依赖项中。
  7. 为CommonJS模块编写一个Scala.js外观。
  8. 使用原始Java库中的确切接口编写Scala.js门面的包装。如果Scala.js支持,请添加任何IO和其他JSweet不兼容的功能。