【发布时间】:2014-05-29 11:23:56
【问题描述】:
我已经构建了一个小对象,它可以即时解释 scala 代码并从中获取值。
object Interpreter {
import scala.tools.nsc._
import scala.tools.nsc.interpreter._
class Dummy
val settings = new Settings
settings.usejavacp.value = false
settings.embeddedDefaults[Dummy] // to make imain useable with sbt.
val imain = new IMain(settings)
def run(code: String, returnId: String) = {
this.imain.beQuietDuring{
this.imain.interpret(code)
}
val ret = this.imain.valueOfTerm(returnId)
this.imain.reset()
ret
}
}
object Main {
def main(args: Array[String]) {
println(Interpreter.run("val x = 1", "x"))
}
}
在纯sbt 环境中或由scala 解释器调用此代码可以正常工作!但是如果我在一个简单的play(2.2.2 版)应用程序中运行它,它会在val ret = this.imain.valueOfTerm(returnId) 处获得一个空指针。
play 也使用 modified sbt,因此它应该可以工作。 play 做了什么使这段代码不再起作用?任何想法如何让此代码在play 中工作?
注意
那是用过的build.sbt:
name := "Test"
version := "1.0"
scalaVersion := "2.10.3"
libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value
或者我尝试了这个实现,但它也没有解决问题:
object Interpreter2 {
import scala.tools.nsc._
import scala.tools.nsc.interpreter._
import play.api._
import play.api.Play.current
val settings: Settings = {
lazy val urls = java.lang.Thread.currentThread.getContextClassLoader match {
case cl: java.net.URLClassLoader => cl.getURLs.toList
case _ => sys.error("classloader is not a URLClassLoader")
}
lazy val classpath = urls map {_.toString}
val tmp = new Settings()
tmp.bootclasspath.value = classpath.distinct mkString java.io.File.pathSeparator
tmp
}
val imain = new IMain(settings)
def run(code: String, returnId: String) = {
this.imain.beQuietDuring {
this.imain.interpret(code)
}
val ret = this.imain.valueOfTerm(returnId)
this.imain.reset()
ret
}
}
我发现用于实现第二个实现的有用链接:
【问题讨论】: