问题
In a Scala code, I'd like to create an interpreter that will evaluate some strings which are Scala code, e.g., using ScriptEngine. But I'd like to pass the current variable and type definitions to it so that the code in the strings can use them, as if the new interpreter is forked from the current interpreter.
With ScriptEngine I could use use the "put" method to put bindings into it, but this needs to be explicit and for each variable. And, there's no way to pass a class definition, or a method etc.
Is there a way then, or am I misunderstanding something?
The purpose is to let dynamic code to use prepared data and methods
This is what I can do now:
import javax.script._
val e = new ScriptEngineManager().getEngineByName("scala")
engine.put("x", 123)
engine.eval("val y = x.asInstanceOf[Int] + 100")
This is what I'd like to do:
case class X(a: Int, b: Int)
val x = X(1,2)
engine.eval("val x1 = X(x.a + 1, x.b + 1)") // Use both X and x
回答1:
You can try
val res = engine.eval(
"""case class X(a: Int, b: Int)
|val x = X(1,2)
|val x1 = X(x.a + 1, x.b + 1)""".stripMargin)
Also you can use scala.tools.reflect.ToolBox
.
Use import.
package mypackage
import javax.script._
object App {
val engine = new ScriptEngineManager().getEngineByName("scala")
case class X(a: Int, b: Int)
val x = X(1,2)
val res = engine.eval("import mypackage.App._; val x1 = X(x.a + 1, x.b + 1)")
}
or
package mypackage
import scala.reflect.runtime.universe._
import scala.tools.reflect.ToolBox
object App {
val tb = runtimeMirror(ClassLoader.getSystemClassLoader).mkToolBox()
case class X(a: Int, b: Int)
val x = X(1, 2)
val tree = tb.parse("import mypackage.App._; val x1 = X(x.a + 1, x.b + 1)")
val res = tb.eval(tree)
}
来源:https://stackoverflow.com/questions/56486653/scala-how-to-instantiate-an-interpreter-that-inherits-the-current-context