2016-08-25 2 views
2

Was ist der beste Weg, um einen Code-Ausschnitt zu scala zu injizieren? etwas wie Eval in Javascript und GroovyScriptEngine. Ich möchte meine Regeln/Berechnungen/Formeln außerhalb der eigentlichen Datenverarbeitungsklasse behalten. Ich habe fast 100 Formeln, die ausgeführt werden müssen. Der Datenfluss ist für alle gleich, nur die Formeln ändern sich. Was ist der beste Weg, um es in Scala zu tun? und die Anzahl der Formeln wird mit der Zeit wachsen.Dynamische Code-Auswertung in Scala

+1

Betrachten Sie diese Frage zu lesen - https://stackoverflow.com/questions/1183645/eval-in-scala – tuxdna

Antwort

3

Sie könnten entweder scala-lang API dafür oder twitter-eval verwenden. Hier ist der Ausschnitt aus einem einfachen Anwendungsfall von scala-lang

import scala.tools.nsc.Settings 
import scala.tools.nsc.interpreter.IMain 

object ScalaReflectEvaluator { 

    def evaluate() = { 
    val clazz = prepareClass 
    val settings = new Settings 
    settings.usejavacp.value = true 
    settings.deprecation.value = true 

    val eval = new IMain(settings) 
    val evaluated = eval.interpret(clazz) 
    val res = eval.valueOfTerm("res0").get.asInstanceOf[Int] 
    println(res) //yields 9 
    } 

    private def prepareClass: String = { 
    s""" 
     |val x = 4 
     |val y = 5 
     |x + y 
     |""".stripMargin 
    } 
} 

oder mit Twitter:

import com.twitter.util.Eval 

object TwitterUtilEvaluator { 

    def evaluate() = { 
    val clazz = prepareClass 
    val eval = new Eval 
    eval.apply[Int](clazz) 
    } 

    private def prepareClass: String = { 
    s""" 
     |val x = 4 
     |val y = 5 
     |x + y 
     |""".stripMargin 
    } 
} 

Ich bin nicht in der Lage es im Moment zu kompilieren zu überprüfen, ob ich etwas verpasst haben, aber Sie sollten erhalten die Idee.

+0

ist es möglich, eine Variable, dass passieren? also zum beispiel könnte man println (z) im code zum auswerten verwenden und es würde "test" drucken – Nicofisi

+0

ich glaube nicht dass du kannst. Sie befinden sich in einem anderen Laufzeitkontext. Das ist also kein Scripting-ähnlicher Code-Injection. siehe: JSR-223: https://www.jcp.org/en/jsr/detail?id=223 – linehrr

2

Ich habe festgestellt, dass scala.tools.reflect.ToolBox ist das schnellste Eval in Scala (gemessene Interpreter, twitter Eval und benutzerdefinierte Tool). Es ist API:

import scala.reflect.runtime.universe 
import scala.tools.reflect.ToolBox 
val tb = universe.runtimeMirror(getClass.getClassLoader).mkToolBox() 
tb.eval(tb.parse("""println("hello!")"""))