web-dev-qa-db-fra.com

"eval" dans Scala

Scala peut-il être utilisé pour créer un script pour une application Java?

J'ai besoin de charger un morceau de code Scala à partir de Java, de définir une étendue d'exécution pour celui-ci (données exposées par l'application hôte), de l'évaluer et d'en récupérer un objet de résultat.

La documentation Scala montre à quel point il est facile d'appeler le code compilé Scala de Java (car il devient Bytecode JVM).

Mais comment puis-je évaluer une expression Scala à la volée (depuis Java ou si c'est plus facile, depuis Scala))?

Pour de nombreuses autres langues, il existe l'interface javax.scripting. Scala ne semble pas le prendre en charge, et je n'ai rien trouvé dans les documents d'interopérabilité Java/Scala qui ne repose pas sur une compilation anticipée.

56
Thilo

Scala n'est pas un langage de script. Il peut ressembler un peu à un langage de script, et les gens peuvent le préconiser à cette fin, mais il ne s'intègre pas vraiment dans le cadre de script JSR 223 (qui est orienté vers des langages typés dynamiquement). Pour répondre à votre question d'origine, Scala n'a pas de fonction eval comme Java n'a pas de eval). Une telle fonction n'aurait vraiment de sens pour aucun de ces langages étant donné leur nature intrinsèquement statique.

Mon conseil: repensez votre code pour ne pas avoir besoin de eval (vous en avez rarement, même dans les langues qui en disposent, comme Ruby). Alternativement, vous ne voulez peut-être pas utiliser Scala du tout pour cette partie de votre application. Si vous avez vraiment besoin de eval, essayez d'utiliser JRuby. JRuby, Scala et Java maillage très bien ensemble. Il est assez facile d'avoir une partie de votre système en Java, une partie en Scala et une autre partie) (le bit qui nécessite eval) en Ruby.

50
Daniel Spiewak

c'est maintenant 2011, et vous pouvez le faire avec scala.tools.nsc.Interpreter

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

66
ninjagecko

Scala a ajouté un support officiel à JSR-223 en 2.11 ( https://issues.scala-lang.org/browse/SI-874 ).

Donc, si vous en avez toujours besoin après avoir réfléchi aux considérations faites dans la réponse actuellement acceptée de Daniel Spiewak (à propos de repenser d'une manière qui n'est pas nécessaire), cela devrait être l'alternative officielle.

21
Oswaldo

Vous pouvez émuler "eval" en prenant scala code, en l'enveloppant dans une classe, en compilant cette classe, en utilisant la réflexion pour créer une nouvelle instance, puis en l'appelant. C'est un peu compliqué, et le scala est très lent (de l'ordre de 2 secondes) à initialiser, mais il fonctionne très bien.

Il y a une bibliothèque pour cela ici, appelée "util-eval": https://github.com/Twitter/util/

Le code en question réside ici: https://github.com/Twitter/util/blob/master/util-eval/src/main/scala/com/Twitter/util/Eval.scala

Cela fonctionne comme ceci:

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

Je ne sais pas si c'est une bonne solution, mais j'ai résolu ce problème en utilisant toolbox.parse et toolbox.eval

Pour avoir un eval en Scala vous devez:

  1. Importer scala-reflect

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

  1. Utilisez eval à partir de la boîte à outils:
  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
8
gun

Vous pouvez toujours utiliser scalac pour compiler une classe scala puis charger cette classe dynamiquement. Mais je suppose que ce n'est pas ce que vous recherchez.

2
Kim Stebel