Условная компиляция блоков кода в Scala

Мне было интересно, есть ли способ условно исключить блок кода из компиляции в Scala с использованием флагов времени компиляции (то есть некоторого грубого эквивалента #define семейства C). Я знаю, что нет прямого аналога, и я не думаю, что макросы Scala - это то, что мне нужно, поэтому мне было интересно, есть ли другой способ сделать это.

В моем текущем случае (и я привожу это только в качестве примера, потому что в прошлом у меня были другие случаи, которые вызывали тот же вопрос), я создаю библиотеку на ScalaJS. Библиотека является интерфейсным компонентом и в основном будет использоваться моим приложением, которое также использует ScalaJS. Однако я хотел бы позволить этому компоненту вызываться собственным Javascript в других проектах, которые не используют ScalaJS. Таким образом, я хочу иметь настраиваемый пользователем флаг, который будет переключать экспорт символов в собственный Javascript по запросу.

Нет смысла экспортировать эти флаги по умолчанию (в моем приложении), поскольку единственный другой код, вызывающий их, будет другим кодом ScalaJS, и поэтому накладные расходы на экспортируемые символы бессмысленны. Поддержание двух отдельных веток кода для чего-то столь тривиального тоже кажется бесполезным.

Это в основном то, что я имел в виду (конечно, псевдокод):

...

#if JS_EXPORT
@JSExport
#endif
case class componentProps(
    #if JS_EXPORT
    @(JSExport @field) 
    #endif
    val propertyOne: Int
    #if JS_EXPORT
    @(JSExport @field) 
    #endif
    val propertyTwo: String
)

...

Мне хорошо известно, что препроцессора нет, и приведенное выше предназначено только как псевдокод. Мне просто интересно, есть ли способ добиться чего-то подобного без лишних накладных расходов, таких как использование отражения (потому что я уверен, что это приведет к большему снижению производительности, чем простой экспорт по умолчанию).

Кроме того, мне удалось найти этот вопрос: Условная компиляция в Scala. Но это не то, что мне нужно.


person Ruslan    schedule 06.12.2015    source источник
comment
Вы можете создать свой собственный простой препроцессор как sbt sourceGenerator.   -  person sjrd    schedule 06.12.2015
comment
@sjrd Это был бы интересный проект как способ глубже проникнуть в Scala. Тем не менее, этот вопрос также заключался в том, чтобы оценить общее отношение к чему-то вроде этого и убедиться, что нет ничего плохого в моем собственном мышлении (т.е., возможно, я что-то неправильно понимаю), когда мне нужна такая функция, потому что для меня это не проблема. . Как вы думаете, будет ли это интересно?   -  person Ruslan    schedule 07.12.2015
comment
возможно, вы попытаетесь использовать elidable, хотя есть несколько других #default: stackoverflow.com/questions/8388952/   -  person 余杰水    schedule 08.12.2015


Ответы (2)


Нет никакого способа, который не был бы полным взломом, сделать это в исходном коде.

Стандартные способы реализации двойных проектов JVM / JS - минимизировать количество исходных файлов, в которых возникает разница, и делать это вручную для них (почти все проекты Ли Хаойи похожи на это - ознакомьтесь со структурой fastparse для пример); или иметь две ветки git, которые имеют два варианта и объединять все изменения от одного к другому.

person Rex Kerr    schedule 06.12.2015
comment
Это то, что я боялся услышать. Я действительно удивлен, что никто еще не придумал препроцессор для Scala, особенно потому, что Scala имеет ТАКОЕ много функций для каждого вообразимого варианта использования, но тот, который настолько прост (и который может быть применим к довольно большому количеству вариантов использования). , особенно настольные приложения) отсутствует. Если только я чего-то не упускаю. Однако почти кажется естественным, что что-то вроде этого доступно, по крайней мере, как задача sbt. - person Ruslan; 06.12.2015
comment
Сведение к минимуму количества мест / исходных файлов, в которых живет код конкретной платформы, как правило, является хорошей практикой, полностью независимо от Scala.js =) - person Li Haoyi; 06.12.2015

В вашем конкретном случае вам не нужно иметь для этого определенный исходный код: Scala.js предоставляет библиотеку scalajs-stubs. Это целевая библиотека JVM, которая содержит аннотации-заглушки для аннотаций Scala.js (@JSExport и др.).

Вы можете добавить его как «предоставленную» зависимость к вашему проекту JVM, чтобы он не понадобился во время выполнения:

libraryDependencies +=
  "org.scala-js" %% "scalajs-stubs" % scalaJSVersion % "provided"

Обратите внимание, что аннотации не статичны, т.е. они даже не появятся в .class файлах.

Подробнее о scala-js.org (внизу страницы ).

person gzm0    schedule 07.12.2015
comment
Спасибо! Это полезно знать, но это не имеет прямого отношения к моему случаю, потому что мой проект не является двойным целевым ScalaJS / JVM; вместо этого это две версии ScalaJS (одна для экспорта, которая будет использоваться необработанным Javascript, другая для использования другим кодом ScalaJS). - person Ruslan; 08.12.2015