java - "Eval" en Scala
scripting embedding (6)
¿Se puede usar Scala para crear secuencias de comandos de una aplicación Java?
Necesito cargar un fragmento de código Scala de Java, configurar un ámbito de ejecución para él (datos expuestos por la aplicación host), evaluarlo y recuperar un objeto resultante de él.
La documentación de Scala muestra lo fácil que es llamar al código Scala compilado de Java (porque se convierte en un bytecode de JVM normal).
Pero, ¿cómo puedo evaluar una expresión de Scala sobre la marcha (desde Java o si es más fácil, desde dentro de Scala)?
Para muchos otros idiomas, existe la interfaz javax.scripting. Scala no parece soportarlo, y no pude encontrar nada en los documentos de interoperabilidad de Java / Scala que no dependan de la compilación anticipada.
No estoy seguro, si esto es una buena manera, pero resolví este problema con el uso de toolbox.parse
y toolbox.eval
Para tener una evaluación en Scala debes:
- Importar scala-reflect
libraryDependencies += "org.scala-lang" % "scala-reflect" % "2.11.7"
- Use eval desde la caja de herramientas:
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
Puede emular "eval" tomando el código scala, envolviéndolo en una clase, compilando esa clase, usando la reflexión para crear una nueva instancia, y luego llamándola. Está un poco involucrado, y el compilador scala es muy lento (del orden de 2 segundos) para inicializarse, pero funciona bien.
Aquí hay una biblioteca, llamada "util-eval": https://github.com/twitter/util/
El código en cuestión vive aquí: https://github.com/twitter/util/blob/master/util-eval/src/main/scala/com/twitter/util/Eval.scala
Funciona así:
val sum = Eval[Int]("1 + 1")
// sum will be 2
Scala ha agregado soporte oficial a JSR-223 en 2.11 ( https://issues.scala-lang.org/browse/SI-874 ).
Entonces, si aún lo necesita después de pensar en las consideraciones hechas en la respuesta actualmente aceptada de Daniel Spiewak (sobre el replanteamiento de una manera que no es necesaria), esta debería ser la alternativa oficial.
Siempre puede usar scalac para compilar una clase scala y luego cargar esa clase dinámicamente. Pero supongo que eso no es lo que buscas.
ahora es 2011, y puedes hacerlo con scala.tools.nsc.Interpreter
ver http://blog.darevay.com/2009/01/remedial-scala-interpreting-scala-from-scala/
Scala no es un lenguaje de scripting. Puede parecer algo así como un lenguaje de scripting, y las personas pueden recomendarlo para ese fin, pero realmente no encaja bien dentro del marco de scripting JSR 223 (que está orientado a los lenguajes de tipado dinámico). Para responder a su pregunta original, Scala no tiene una función eval
como Java no tiene una eval
. Tal función no tendría sentido para ninguno de estos lenguajes dada su naturaleza intrínsecamente estática.
Mi consejo: reconsidere su código para que no lo necesite (lo hace raramente, incluso en idiomas que lo tienen, como Ruby). Alternativamente, tal vez no desee usar Scala en absoluto para esta parte de su aplicación. Si realmente necesita una eval
, intente utilizar JRuby. JRuby, Scala y Java se unen muy bien. Es bastante fácil tener parte de tu sistema en Java, parte en Scala y otra parte (el bit que requiere eval
) en Ruby.