Может ли JSweet эффективно переносить библиотеки Java для использования в перекрестных проектах Scala.js?

В поисках способов сделать библиотеки Java доступными для сторон JavaScript и JVM в кросс- сборных проектах Scala.js, рассмотрите следующий эксперимент:

Представьте, что проекту Scala.js требуются расширенные математические возможности, такие как декомпозиция Singular Value. Хотя в мире JavaScript есть Numeric.js, а в мире JVM есть много вариантов, в том числе JAMA, на момент постановки этого вопроса не существовало перекрестного решения Scala.js.

Какие у нас есть варианты?

  1. Напишите заново или портируйте матричную библиотеку для Scala.js.
  2. Оберните фасады Numeric.js и JAMA в общий интерфейс Scala.js.
  3. Напишите фасады для Numeric.js, затем скомпилируйте его с помощью Nashorn для поддержки JVM.
  4. Переведите 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:

  1. Закажите исходный код Java.
  2. Удалите IO и другие несовместимые функции JSweet.
  3. Скомпилируйте его с помощью JSweet в качестве модуля Node.js.
  4. Вручную сверните файл package.json и опубликуйте вывод транспортера JSweet на npm.
  5. Добавить ScalaJS-bundler в кросс-скомпилированный проект Scala.js; включите модуль CommonJS из пятого шага.
  6. Включите версию Java в зависимости JVM build.sbt.
  7. Напишите фасад Scala.js для модуля CommonJS.
  8. Напишите оболочку для фасада Scala.js с точным интерфейсом из исходной библиотеки Java. Добавьте любой IO и другие несовместимые функции JSweet, если Scala.js поддерживает это.
Другие вопросы по тегам