2015-03-31 31 views
3

我发现了一个用于回答Generating a class from string and instantiating it in Scala 2.10的Scala运行时脚本的示例代码,但代码似乎已经过时了2.11-我找不到对应于build.setTypeSignature的任何函数。即使它起作用,代码似乎也很难阅读,并且跟随我。2.11中的Scala脚本

如何在Scala 2.11中编译和执行Scala脚本?

让我们假设我想以下几点:

  • 定义几个变量(名称和值)
  • 编译脚本
  • (可选改善)改变量值
  • 执行脚本

为简单起见,请考虑以下示例:

我要定义以下变量(编程方式,从代码,而不是从脚本文本):

val a = 1 
val s = "String" 

我想下面的脚本进行编译和执行的String"a is 1, s is String"从它返回:

s"a is $a, s is $s" 

我的功能应该如何?

def setupVariables() = ??? 

def compile() = ??? 

def changeVariables() = ??? 

def execute() : String = ??? 
+0

注意:'build.setTypeSignature'被替换为'internal.reificationSupport.setInfo'。另请参阅[Scala 2.11中的变化](http://docs.scala-lang.org/overviews/macros/changelog211.html) - 段落**如何使您的2.10.x宏在2.11.0 **中工作。 – Suma 2015-05-13 08:51:54

回答

2

斯卡拉2.11 adds a JSR-223 scripting engine。它应该给你你正在寻找的功能。正如所有这些动态的东西(包括上面描述中列出的例子)一样,您将会失去类型安全性。你可以在下面看到返回类型总是为Object。

斯卡拉REPL例子:

scala> import javax.script.ScriptEngineManager 

import javax.script.ScriptEngineManager 


scala> val e = new ScriptEngineManager().getEngineByName("scala") 

e: javax.script.ScriptEngine = [email protected] 


scala> e.put("a", 1) 

a: Object = 1 


scala> e.put("s", "String") 

s: Object = String 


scala> e.eval("""s"a is $a, s is $s"""") 

res6: Object = a is 1, s is String` 

的另外例子为下阶2.11.6运行的应用程序:

import javax.script.ScriptEngineManager 

object EvalTest{ 
    def main(args: Array[String]){ 
    val e = new ScriptEngineManager().getEngineByName("scala") 
    e.put("a", 1) 
    e.put("s", "String") 
    println(e.eval("""s"a is $a, s is $s"""")) 
    } 
} 

对于这个应用程序的工作确保包括库相关。

libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value 
+0

这看起来很有希望,但是当我在应用程序(而不是REPL)中运行此应用程序时,出现错误'scala.reflect.internal.MissingRequirementError:未找到编译器镜像中的对象scala。“。我在我的build.sbt中拥有“scala-reflect”,“scala-compiler”和“scala-library”(实际上我已经使用'universe.runtimeMirror'工作了脚本编译,只有变量设置是我的无法做到)。 – Suma 2015-04-03 11:53:47

+0

注意:脚本引擎创建的getEngineByName成功,但在调用''eval''函数时出现异常。 – Suma 2015-04-03 12:05:42

+0

我可以通过使用'e.asInstanceOf [IMain] .settings.usejavacp.value = true'来摆脱异常,但是在第二个脚本执行时会出现非常奇怪的错误(将'IMain'强制转换为'IMain时出现'CaseClassException' ')。我疯狂的猜测在JSR-223风格中嵌入Scala适用于Java应用程序,不适用于Scala应用程序? – Suma 2015-04-03 12:52:53