Scala

时间:2015-12-06 01:32:31

标签: scala compilation conditional-compilation scala-macros scala.js

我想知道是否有办法使用编译时标志(即C系列的#define的一些粗略等价物)有条件地排除在Scala中编译的代码块。我知道没有直接的对应物,我不认为Scala的宏是我需要的,所以我想知道是否有另一种方法可以做到这一点。

在我目前的情况下(我提供这个仅作为一个例子,因为我过去有其他案例提示相同的问题),我正在ScalaJS中构建一个库。该库是一个前端组件,主要由我的应用程序使用 - 它也使用ScalaJS。但是,我想在其他未使用ScalaJS的项目中允许本机Javascript调用此组件。因此,我希望有一个用户可配置的标志,可以根据请求将符号导出切换为本机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
)

...

我很清楚没有预处理器,上面只是伪代码。我只是想知道是否有一种方法可以完成类似的事情,没有不必要的开销,比如使用反射(因为我确信这会提供比默认导出更大的性能)。

此外,我能够找到这个问题:Conditional compilation in Scala。但这不是我需要的。

2 个答案:

答案 0 :(得分:2)

在源代码中没有任何方法可以完全破解。

完成双JVM / JS项目的标准方法是尽量减少发生差异的源文件的数量,并为那些人手动完成(几乎所有的Li Haoyi的项目都是这样的 - 检查结构例如fastparse);或者有两个git分支,它们具有两个变体,并将所有变化从一个变为另一个。

答案 1 :(得分:1)

对于您的特定情况,您无需具有特定的源代码:Scala.js提供scalajs-stubs库。这是一个JVM目标库,包含Scala.js注释的存根注释(@JSExport等)。

您可以将它作为“提供”依赖项添加到您的JVM项目中,因此在运行时不需要它:

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

请注意,注释不是静态的,即它们甚至不会出现在.class文件中。

有关scala-js.org的更多详情(页面底部)。