"eval" in Scala

28,720

Solution 1

Scala is not a scripting language. It may look somewhat like a scripting language, and people may advocate it for that purpose, but it doesn't really fit well within the JSR 223 scripting framework (which is oriented toward dynamically typed languages). To answer your original question, Scala does not have an eval function just like Java does not have an eval. Such a function wouldn't really make sense for either of these languages given their intrinsically static nature.

My advice: rethink your code so that you don't need eval (you rarely do, even in languages which have it, like Ruby). Alternatively, maybe you don't want to be using Scala at all for this part of your application. If you really need eval, try using JRuby. JRuby, Scala and Java mesh very nicely together. It's quite easy to have part of your system in Java, part in Scala and another part (the bit which requires eval) in Ruby.

Solution 2

it's now 2011, and you can do so with scala.tools.nsc.Interpreter see http://blog.darevay.com/2009/01/remedial-scala-interpreting-scala-from-scala/

use scala.tools.nsc.interpreter

Solution 3

Scala has added official support to JSR-223 in 2.11 (https://issues.scala-lang.org/browse/SI-874).

So if you still need it after thinking about the considerations made in the currently accepted answer from Daniel Spiewak (about rethinking in a way it is not needed), this should be the official alternative.

Solution 4

You can emulate "eval" by taking scala code, wrapping it in a class, compiling that class, using reflection to create a new instance, and then calling it. It's a little involved, and the scala compiler is very slow (on the order of 2 seconds) to initialize, but it works fine.

There's a library for it here, called "util-eval": https://github.com/twitter/util/

The code in question lives here: https://github.com/twitter/util/blob/master/util-eval/src/main/scala/com/twitter/util/Eval.scala

It works like this:

val sum = Eval[Int]("1 + 1")
// sum will be 2

Solution 5

I am not sure, if this is a good way, but I solved this problem with using toolbox.parse and toolbox.eval

To have an eval in Scala you have to:

  1. Import scala-reflect

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

  1. Use eval from toolbox:

  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

Share:
28,720
hansvb
Author by

hansvb

Updated on July 09, 2022

Comments

  • hansvb
    hansvb almost 2 years

    Can Scala be used to script a Java application?

    I need to load a piece of Scala code from Java, set up an execution scope for it (data exposed by the host application), evaluate it and retrieve a result object from it.

    The Scala documentation shows how easy it is to call compiled Scala code from Java (because it gets turned into to regular JVM bytecode).

    But how can I evaluate a Scala expression on the fly (from Java or if that is easier, from within Scala) ?

    For many other languages, there is the javax.scripting interface. Scala does not seem to support it, and I could not find anything in the Java/Scala interoperability docs that does not rely on ahead-of-time compilation.

  • Kevin Peterson
    Kevin Peterson almost 15 years
    +1 Scala does support being run from a text file like a scripting language, but it isn't a scripting language. It sounds like the author is interested in providing a scripting interface to his app, which JavaScript, Groovy or Lua would be better suited for.
  • hansvb
    hansvb almost 15 years
    Well, that would work. The "interpreter" invokes the compiler internally anyway. But it seems that the compiler is not any more straightforward to embed than the interpreter is.
  • Kim Stebel
    Kim Stebel almost 15 years
    Depends on how you want to "embed" it. The easiest way is to call it as an external program. But if you want better integration of your program with the compiler, you can find a discussion of how to do that here: nabble.com/Compiler-API-td12050645.html
  • hansvb
    hansvb almost 15 years
    Okay, I am going to grudgingly accept this answer. Too bad, since the Scala docs seem to highlight their interpreter as a significant feature. One would think that this would be using some kind of "eval" under the hood. Apparently not.
  • Daniel Spiewak
    Daniel Spiewak almost 15 years
    The interpreter is not a language feature, it's just part of the tool set. Look at Haskell as a good example. GHC Haskell provides the ghc tool, which is the compiler, and ghci, which is the interactive shell. It's an "interpreter" just like Scala's REPL, but there is really no way to use it within a Haskell function. As mentioned previously, to allow this would be horribly unsafe (type-wise) and not in line with the language as a whole.
  • Randall Schulz
    Randall Schulz about 13 years
    That is not a "third-party" package, it's part of the Scala language implementation proper.
  • srparish
    srparish almost 13 years
    This is not entirely true. GHI exposes much of it's functionality as an api, which is unfortunately not very easy to use. There are packages that help you with this: hackage.haskell.org/package/hint
  • Kipton Barros
    Kipton Barros almost 13 years
    It's worth pointing out that the interpreter is contained in the Scala compiler, not the public facing standard library API, and is therefore subject to change. The linked blog was written for Scala version 2.8. As of version 2.9, one must replace scala.tools.nsc.Interpreter with scala.tools.nsc.interpreter.IMain. The rest of the code in the blog should work the same.
  • ninjagecko
    ninjagecko almost 13 years
    @Kipton and nsc.interpreter.ISettings as well I think. Unfortunately I and others are getting values ClassCastExceptions: stackoverflow.com/questions/6367393/… (when I tried to test out my answer recently) and stackoverflow.com/questions/6164138/scala-as-scripting-langu‌​age/…
  • Kipton Barros
    Kipton Barros almost 13 years
    you're having problems with the classloader? My workaround is to set the Java classpath, and create the interpreter with "usejavacp". Also, you might find the answer here relevant: stackoverflow.com/questions/4121567/…
  • Bill
    Bill over 11 years
    As of 2.10, you can build source trees and compile them with scala.tools.reflect.ToolBox#eval. See slide 35 of scalamacros.org/talks/2012-04-28-MetaprogrammingInScala210.p‌​df
  • Mike Morearty
    Mike Morearty over 9 years
    Nice! Although the above syntax still works, it now prints a warning: "object Eval in package util is deprecated: use a throw-away instance of Eval instead." The new recommended code is: val i: Int = new Eval()("1 + 1"). See Eval.scala's different apply() functions for variations (reading from files or InputStreams).
  • ZhekaKozlov
    ZhekaKozlov almost 9 years
    Doesn't work: "object tools is not a member of package scala"
  • Ruslan
    Ruslan over 8 years
    @woky And the answer states pretty clearly: " Scala does not have an eval function just like Java does not have an eval". The answerer did not say what he thinks about Scala, he said that Scala is not a scripting language - which it is not. And that's a fact. Ask a community of JS devs how to do inline assembly for the device driver that you're building in Javascript - and you'll get the same answer: "you're using the wrong language". And that would not be an opinion about inline assembly or device drivers.
  • Dmytro
    Dmytro almost 8 years
    @woky agreed, I want eval so I can have my scala be able to write itself the same way javascript can write itself(since javascript is able to stringify its own code as well as eval it). With minor changes scala could be javascript on steroids(multithreaded).
  • Daniel Slapman
    Daniel Slapman almost 8 years
    It's required to reference "org.scala-lang" % "scala-compiler" along to "scala-reflect", then the code above compiles and runs fine.
  • Det
    Det over 6 years
    404: Page Not Found
  • user118967
    user118967 about 6 years
    "Such a function wouldn't really make sense for either of these languages given their intrinsically static nature."| I think this sentence needs more justification. I don't see any intrinsic problem in performing an eval on a snippet of text that contains code in a statically-typed language.
  • som-snytt
    som-snytt over 5 years
    it's 2018 going on 2019.
  • som-snytt
    som-snytt over 5 years
    This answer may have been more true ten years ago, but it's called "Scala" because the language (as such) is scalable, from small scripts to apps. The tooling could be improved for evaluation in dynamic contexts, but scripting (as such) is clearly part of its mandate.
  • Z4-tier
    Z4-tier over 2 years
    importing scala.tools.nsc.Interpreter gives a deprecation warning. Link is dead. It is 2022.... sorry, have to downvote. Please fix this answer.
  • ninjagecko
    ninjagecko over 2 years
    @Z4-tier feel free to let us know if interpreter is deprecated