Может ли JSweet эффективно переносить библиотеки Java для использования в перекрестных проектах Scala.js?
В поисках способов сделать библиотеки Java доступными для сторон JavaScript и JVM в кросс- сборных проектах Scala.js, рассмотрите следующий эксперимент:
Представьте, что проекту Scala.js требуются расширенные математические возможности, такие как декомпозиция Singular Value. Хотя в мире JavaScript есть Numeric.js, а в мире JVM есть много вариантов, в том числе JAMA, на момент постановки этого вопроса не существовало перекрестного решения Scala.js.
Какие у нас есть варианты?
- Напишите заново или портируйте матричную библиотеку для Scala.js.
- Оберните фасады Numeric.js и JAMA в общий интерфейс Scala.js.
- Напишите фасады для Numeric.js, затем скомпилируйте его с помощью Nashorn для поддержки JVM.
- Переведите JAMA в JavaScript с помощью JSweet и создайте соответствующие фасады Scala.js.
Этот вопрос отражает вариант 4.
После восстановления JAMA для транспортера JSweet, публикации переданного JavaScript в виде модуля CommonJS через npm и написания фасадов Scala.js для модуля CommonJS, код Scala теперь может обращаться к Jama на стороне JVM и к его порту на стороне JS,
К сожалению, основная структура данных на стороне JVM имеет тип: double[][], Array[Array[Double]] в синтаксисе Scala, но JSweet преобразует его в тип массива JavaScript, js.Array[js.Array[Double]] в синтаксисе Scala.js.
Теперь, с точки зрения кросс-сборки Scala.js, существуют две одинаково названные, эквивалентно функциональные, но совершенно разные и отдельные библиотеки.
Из синтаксиса Scala мы можем построить трехмерную матрицу идентичности на стороне JS следующим образом:
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?
Вы бы предложили совершенно другой подход, чтобы сделать библиотеки Java доступными для кросс-собранных проектов Scala.js?
2 ответа
Позвольте мне начать с простого вопроса:
Есть ли трюк, чтобы приравнять js.Array и Array?
Нет, такого "подвоха" нет. Эти структуры данных принципиально отличаются. js.Array
Длина переменной является переменной и может быть исправлена с помощью дополнительных свойств. Array
массив Java с фиксированной длиной Если бы был какой-то способ приравнять их, Scala.js сделал бы это для вас, как и для Double
а также number
,
Одним из относительно простых способов унификации API-интерфейсов было бы перестроить API-интерфейс JAMA в коде Scala.js, где каждый класс представляет собой обертку для фасадного JS-класса, поступающего из скомпилированной библиотеки JSweet. Это позволяет API-интерфейсу уровня Scala JAMA быть в точности эквивалентным между Scala/JVM и Scala.js. Для репликации API требуется некоторый объем написания кода, но, по крайней мере, тело методов не нужно переписывать.
Совершенно другой подход, очень радикальный и требующий безумного количества человеко-часов, заключался бы в том, чтобы компилятор JSweet создавал файлы Scala.js IR (.sjsir) вместо файлов.js. Таким образом, вы можете связать сгенерированные JSweet файлы.sjsir для JAMA вместе с сгенерированными Scala.js файлами.sjsir для вашего приложения. Это даст максимальную производительность, так как оптимизатор Scala.js сможет оптимизировать через границы приложения / библиотеки.
Рецепт для портирования библиотек Java в Scala.js:
- Закажите исходный код Java.
- Удалите IO и другие несовместимые функции JSweet.
- Скомпилируйте его с помощью JSweet в качестве модуля Node.js.
- Вручную сверните файл package.json и опубликуйте вывод транспортера JSweet на npm.
- Добавить ScalaJS-bundler в кросс-скомпилированный проект Scala.js; включите модуль CommonJS из пятого шага.
- Включите версию Java в зависимости JVM build.sbt.
- Напишите фасад Scala.js для модуля CommonJS.
- Напишите оболочку для фасада Scala.js с точным интерфейсом из исходной библиотеки Java. Добавьте любой IO и другие несовместимые функции JSweet, если Scala.js поддерживает это.