【问题标题】:Scala script in 2.112.11 中的 Scala 脚本
【发布时间】:2015-03-31 16:23:06
【问题描述】:

我找到了一个 Scala 运行时脚本的示例代码来回答 Generating a class from string and instantiating it in Scala 2.10,但是该代码对于 2.11 来说似乎已经过时 - 我找不到任何与 build.setTypeSignature 对应的函数。即使它有效,代码似乎也难以阅读和理解。

如何在 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 = ???

【问题讨论】:

  • 注意:build.setTypeSignature 已替换为 internal.reificationSupport.setInfo。另请参阅Changes in Scala 2.11 - 段落 如何使您的 2.10.x 宏在 2.11.0 中工作

标签: scala reflection scripting compilation


【解决方案1】:

Scala 2.11 adds 一个 JSR-223 scripting engine。它应该为您提供您正在寻找的功能。提醒一下,与所有这些动态事物一样,包括上面描述中列出的示例,您将失去类型安全性。您可以在下面看到返回类型始终为 Object。

Scala REPL 示例:

scala> import javax.script.ScriptEngineManager

import javax.script.ScriptEngineManager


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

e: javax.script.ScriptEngine = scala.tools.nsc.interpreter.IMain@566776ad


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`

作为在 scala 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

【讨论】:

  • 这看起来很有希望,但是当我在我的应用程序(不是 REPL)中运行它时,我收到错误 scala.reflect.internal.MissingRequirementError: object scala in compiler mirror not found.。我的 build.sbt 中有所有“scala-reflect”、“scala-compiler”和“scala-library”(实际上我已经使用universe.runtimeMirror 进行了脚本编译,只有变量设置是我无法做到的做)。
  • 注意:脚本引擎创建 getEngineByName 成功,但在其上调用 eval 函数时出现异常。
  • 我可以通过使用e.asInstanceOf[IMain].settings.usejavacp.value = true 摆脱异常,但是在第二次执行脚本时会遇到非常奇怪的错误(CaseClassExceptionIMain 转换为IMain 时)。我猜想以 JSR-223 风格嵌入 Scala 是为 Java 应用程序设计的,而不是为 Scala 应用程序设计的?
  • 此代码只是 POC。它也将在应用程序中运行。也许您可以提供您的应用程序代码。
  • 除了 repl 代码之外,我还添加了一个示例应用程序。我想我记得在某处读到过一些早期版本的 Scala 脚本引擎存在问题。也许尝试运行 2.11.6?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-06
相关资源
最近更新 更多