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 解决方案。
我们有什么选择?
- 为Scala.js重新编写或移植一个矩阵库。
- 将 Numeric.js 门面和 JAMA 包装到一个通用的 Scala.js 界面中。
- 为 Numeric.js 编写外观,然后使用 Nashorn 编译它以获得 JVM 支持。
- 将 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 会为您做到这一点,就像 Double
和 number
.
一样
统一 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 的方法:
- 获取 Java 源代码。
- 删除 IO 和其他 JSweet 不兼容的功能。
- 将其与 JSweet 编译为 Node.js 模块。
- 手动滚动 package.json 文件并在 npm 上发布 JSweet 转译器输出。
- 将 ScalaJS-bundler 添加到交叉编译的 Scala.js 项目中;包括第五步中的 CommonJS 模块。
- 在 build.sbt 的 JVM 依赖项中包含 Java 版本。
- 为 CommonJS 模块编写一个 Scala.js 门面。
- 使用原始 Java 库中的确切接口为 Scala.js 门面编写一个包装器。如果 Scala.js 支持,添加任何 IO 和其他 JSweet 不兼容的功能。
在寻找使 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 解决方案。
我们有什么选择?
- 为Scala.js重新编写或移植一个矩阵库。
- 将 Numeric.js 门面和 JAMA 包装到一个通用的 Scala.js 界面中。
- 为 Numeric.js 编写外观,然后使用 Nashorn 编译它以获得 JVM 支持。
- 将 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 会为您做到这一点,就像 Double
和 number
.
统一 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 的方法:
- 获取 Java 源代码。
- 删除 IO 和其他 JSweet 不兼容的功能。
- 将其与 JSweet 编译为 Node.js 模块。
- 手动滚动 package.json 文件并在 npm 上发布 JSweet 转译器输出。
- 将 ScalaJS-bundler 添加到交叉编译的 Scala.js 项目中;包括第五步中的 CommonJS 模块。
- 在 build.sbt 的 JVM 依赖项中包含 Java 版本。
- 为 CommonJS 模块编写一个 Scala.js 门面。
- 使用原始 Java 库中的确切接口为 Scala.js 门面编写一个包装器。如果 Scala.js 支持,添加任何 IO 和其他 JSweet 不兼容的功能。