[Scala]Scalaでeval
Rubyのように文字列をScalaスクリプトとしてプログラム内でevalする方法。
scala-compiler.jarの中にscalaインタプリタが使っているクラスInterpreter(そのまんま)があるので、これでevalできる。
package jp.hogehoge import scala.tools.nsc._ import scala.util.DynamicVariable class Evaluator { val i = new Interpreter(new Settings(null)) def eval(line: String): Any = { i.interpret("jp.hogehoge.Evaluator.result.value = " + line) Evaluator.result.value } } object Evaluator { val result = new DynamicVariable[Any](()) } object EvalTest { def main(args: Array[String]): Unit = { val e = new Evaluator val r = e.eval("jp.hogehoge.Hoge.somefunc") println(r) } } object Hoge { def somefunc = "mogemoge" }
解説
- Interpreter::interpretは式の評価値を返してくれない。
- なので、グローバルな変数Evaluator.resultに一旦結果を代入するコードをeval文字列の中に追加する。
- Evaluatorがマルチスレッドで使われる時に備えて、Evaluator.resultをDynamicVariableにしておく。
- 注意点
- ひとつinterpretするだけで平均30ミリ秒くらいはかかるので、ループの中でぶん回すのはやめたほうがいいと思う。
- クラスパスにあるものは何でも実行できる諸刃の剣なので、サニタイズを忘れずに。