JSweet 能否移植 Java 库用于交叉构建的 Scala.js 项目?

Can JSweet viably port Java libraries for use in cross-built Scala.js projects?

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

假设一个 Scala.js 项目需要高级矩阵数学功能,例如 Singular Value Decomposition. Although the JavaScript world has Numeric.js and the JVM world has many options, JAMA 尤其是在提出此问题时不存在交叉构建 Scala.js 解决方案。

我们有什么选择?

  1. 为Scala.js重新编写或移植一个矩阵库。
  2. 将 Numeric.js 门面和 JAMA 包装到一个通用的 Scala.js 界面中。
  3. 为 Numeric.js 编写外观,然后使用 Nashorn 编译它以获得 JVM 支持。
  4. 将 JAMA 转译为 Java具有 JSweet 和时尚适当的 Scala.js 外观的脚本。

这个问题反映了选项 4。

在为 CommonJS 模块重新调整 JAMA for the JSweet transpiler, publishing the transpiled JavaScript as a CommonJS module through npm, and writing Scala.js facades 之后,Scala 代码现在可以在 JVM 端访问 Jama,并在 JS 端访问它的一个端口。

不幸的是,JVM端的核心数据结构在Scala语法中有type: 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 等同于数组?​​

您是否建议采用一种完全不同的方法来使 Java 库可供交叉构建的 Scala.js 项目访问?

让我从简单的问题开始:

Is there a trick to equate js.Array and Array?

不,没有这样的"trick"。这些数据结构 根本不同的。 js.Array 的长度是可变的,可以用附加属性进行修补。 Array是Java的定长数组。如果有任何方法可以将它们等同起来,Scala.js 会为您做到这一点,就像 Doublenumber.

一样

统一 API 的一个相对简单的方法是在 Scala.js 代码中重建 JAMA 的 API,其中每个class 是来自 JSweet 编译库的外观 JS class 的包装器。这使得 JAMA 的 Scala 级别 API 在 Scala/JVM 和 Scala.js 之间完全等价。它确实需要编写一些代码来复制 APIs,但至少不需要重写方法的主体。

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

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

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