Scala中的“eval”

时间:2009-07-26 03:23:22

标签: java scala scripting embedding

可以使用Scala编写Java应用程序脚本吗?

我需要从Java加载一段Scala代码,为它设置执行范围(主机应用程序公开的数据),评估它并从中检索结果对象。

Scala文档显示了从Java调用编译的Scala代码是多么容易(因为它变成了常规的JVM字节码)。

但是我如何动态评估Scala表达式(从Java或者如果在Scala中更容易)?

对于许多其他语言,有javax.scripting接口。 Scala似乎不支持它,我在Java / Scala互操作性文档中找不到任何不依赖于提前编译的东西。

6 个答案:

答案 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.parsetoolbox.eval解决了这个问题

要在Scala中使用eval,您必须:

  1. 导入scala-reflect
  2. libraryDependencies += "org.scala-lang" % "scala-reflect" % "2.11.7"

    1. 使用工具箱中的eval:
    2.   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类,然后动态加载该类。但我猜这不是你想要的。