可以使用Scala编写Java应用程序脚本吗?
我需要从Java加载一段Scala代码,为它设置执行范围(主机应用程序公开的数据),评估它并从中检索结果对象。
Scala文档显示了从Java调用编译的Scala代码是多么容易(因为它变成了常规的JVM字节码)。
但是我如何动态评估Scala表达式(从Java或者如果在Scala中更容易)?
对于许多其他语言,有javax.scripting接口。 Scala似乎不支持它,我在Java / Scala互操作性文档中找不到任何不依赖于提前编译的东西。
答案 0 :(得分:65)
现在是2011年,您可以使用scala.tools.nsc.Interpreter
请参阅http://blog.darevay.com/2009/01/remedial-scala-interpreting-scala-from-scala/
答案 1 :(得分:49)
Scala不是一种脚本语言。它可能看起来像某种脚本语言,人们可能会为此目的提倡它,但它并不适合JSR 223脚本框架(面向动态类型语言)。要回答您的原始问题,Scala没有eval
函数,就像Java没有eval
一样。鉴于这些语言具有内在的静态性质,这种功能对这两种语言都没有意义。
我的建议:重新考虑你的代码,这样你就不需要eval
(你很少这样做,即使是拥有它的语言,比如Ruby)。或者,也许您根本不想在应用程序的这一部分中使用Scala。如果您确实需要eval
,请尝试使用JRuby。 JRuby,Scala和Java很好地融合在一起。使用Java部分系统,部分使用Scala和使用Ruby中的另一部分(需要eval
的部分)非常容易。
答案 2 :(得分:21)
Scala在2.11(https://issues.scala-lang.org/browse/SI-874)中添加了对JSR-223的官方支持。
因此,如果你在考虑Daniel Spiewak当前接受的答案中所做的考虑后仍然需要它(关于以某种方式重新思考它是不需要的),这应该是官方的选择。
答案 3 :(得分:16)
您可以通过使用scala代码,将其包装在类中,编译该类,使用反射创建新实例,然后调用它来模拟“eval”。它有点牵扯,并且scala编译器非常慢(大约2秒)进行初始化,但它工作正常。
这里有一个库,名为“util-eval”:https://github.com/twitter/util/
有问题的代码存在于此:https://github.com/twitter/util/blob/master/util-eval/src/main/scala/com/twitter/util/Eval.scala
它的工作原理如下:
val sum = Eval[Int]("1 + 1")
// sum will be 2
答案 4 :(得分:8)
我不确定,如果这是一个好方法,但我使用toolbox.parse
和toolbox.eval
解决了这个问题
要在Scala中使用eval,您必须:
libraryDependencies += "org.scala-lang" % "scala-reflect" % "2.11.7"
import scala.reflect.runtime.currentMirror
import scala.tools.reflect.ToolBox
val toolbox = currentMirror.mkToolBox()
val as = "2*(2+3)"
val compe = toolbox.eval(toolbox.parse(as))
println(compe.getClass) // prints class java.lang.Integer
println(compe) // prints 10
答案 5 :(得分:2)
您始终可以使用scalac编译scala类,然后动态加载该类。但我猜这不是你想要的。