Scala中的"eval"

Thi*_*ilo 56 java scripting scala embedding

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

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

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

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

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

nin*_*cko 66

它现在是2011年,你可以这样做 scala.tools.nsc.Interpreter

http://blog.darevay.com/2009/01/remedial-scala-interpreting-scala-from-scala/

  • 这不是"第三方"软件包,它是Scala语言实现的一部分. (8认同)
  • 值得指出的是,解释器包含在Scala编译器中,而不是面向公众的标准库API,因此可能会发生变化.链接的博客是为Scala 2.8版编写的.从版本2.9开始,必须用`scala.tools.nsc.interpreter.IMain`替换`scala.tools.nsc.Interpreter`.博客中的其余代码应该是相同的. (7认同)
  • 从2.10开始,您可以使用scala.tools.reflect.ToolBox #eval构建源树并编译它们.请参阅http://scalamacros.org/talks/2012-04-28-MetaprogrammingInScala210.pdf的幻灯片35 (4认同)
  • 404页面不存在 (3认同)

Dan*_*wak 50

Scala不是脚本语言.它看起来有点像脚本语言,人们可能会为此目的提倡它,但它并不适合JSR 223脚本框架(面向动态类型语言).为了回答你原来的问题,Scala没有eval像Java那样的功能eval.鉴于这些语言本质上是静态的,这种功能对于这两种语言都没有意义.

我的建议:重新考虑你的代码,这样你就不需要了eval(你很少这样做,即使是拥有它的语言,比如Ruby).或者,也许您根本不想在应用程序的这一部分中使用Scala.如果您真的需要eval,请尝试使用JRuby.JRuby,Scala和Java很好地融合在一起.使用Java部分系统,部分使用Scala以及eval使用Ruby中的另一部分(需要的部分)非常容易.

  • 解释器不是语言功能,它只是工具集的一部分.看看Haskell就是一个很好的例子.GHC Haskell提供了`ghc`工具,它是编译器,而`ghci`是交互式shell.它就像Scala的REPL一样是"解释器",但实际上没有办法在Haskell函数中使用它.如前所述,允许这种情况非常不安全(类型方面),并且不符合整个语言. (5认同)
  • +1 Scala确实支持从脚本语言等文本文件运行,但它不是脚本语言.听起来作者有兴趣为他的应用程序提供脚本界面,JavaScript,Groovy或Lua更适合. (4认同)
  • @woky答案很清楚:"Scala没有像Java没有eval那样的eval函数".回答者没有说出他对Scala的看法*他说,Scala不是一种脚本语言 - 事实并非如此.这是事实.向JS开发社区询问如何为您在Javascript中构建的设备驱动程序进行内联汇编 - 您将得到相同的答案:"您使用了错误的语言".这不是关于内联汇编或设备驱动程序的意见. (2认同)

小智 21

Scala在2.11(https://issues.scala-lang.org/browse/SI-874)中添加了对JSR-223的官方支持.

因此,如果你在考虑Daniel Spiewak目前接受的答案(在重新思考不需要的方式)中做出的考虑后仍然需要它,那么这应该是官方的选择.


小智 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
Run Code Online (Sandbox Code Playgroud)


gun*_*gun 8

我不确定,如果这是一个好方法,但我使用toolbox.parse和解决了这个问题toolbox.eval

要在Scala中获得评估,您必须:

  1. 导入scala-reflect

libraryDependencies += "org.scala-lang" % "scala-reflect" % "2.11.7"

  1. 使用工具箱中的eval:

  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
Run Code Online (Sandbox Code Playgroud)

  • 需要将 "org.scala-lang" % "scala-compiler" 与 "scala-reflect" 一起引用,然后上面的代码编译并运行良好。 (3认同)