Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic code evaluation in scala

What is the best way to inject a snippet of code to scala? something like eval in javascript and GroovyScriptEngine. I want to keep my rules/computations/formulas outside the actual data processing class. I have close to 100+ formulas to be executed. The data flow is same for all only the formulas change. What is the best way to do it in scala? and the number of formulas will grow over time.

like image 790
Ashok Krishnamoorthy Avatar asked Feb 07 '23 07:02

Ashok Krishnamoorthy


2 Answers

You could use either scala-lang API for that or twitter-eval. Here is the snippet of a simple use case of 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
  }
}

or with 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
  }
}

I am not able to compile it at the moment to check whether I have missed something but you should get the idea.

like image 54
sebszyller Avatar answered Feb 16 '23 03:02

sebszyller


I've found that scala.tools.reflect.ToolBox is the fastest eval in scala (measured interpreter, twitter's eval and custom tool). It's API:

import scala.reflect.runtime.universe
import scala.tools.reflect.ToolBox
val tb = universe.runtimeMirror(getClass.getClassLoader).mkToolBox()
tb.eval(tb.parse("""println("hello!")"""))
like image 25
dveim Avatar answered Feb 16 '23 04:02

dveim