web-dev-qa-db-ja.com

Scalaの "eval"

Scalaを使用してJavaアプリケーションをスクリプト化できますか?

Scalaコードの一部をロードし、実行スコープ(ホストアプリケーションによって公開されたデータ)を設定し、それを評価して、そこから結果オブジェクトを取得する必要があります。

Scalaのドキュメントは、コンパイルされたScalaからコードを呼び出すのがいかに簡単かを示していますJavaから、 JVMバイトコード)。

しかし、Scala式をその場で評価するにはどうすればよいですか(Javaから、またはより簡単な場合は、Scala内から))?

他の多くの言語には、javax.scriptingインターフェースがあります。 Scalaはそれをサポートしていないようで、Java/Scalaの相互運用性のドキュメントで、事前コンパイルに依存しないものは見つかりませんでした。

56
Thilo

Scalaはスクリプト言語ではありません。 lookはスクリプト言語のようであり、人々はその目的のためにそれを主張するかもしれませんが、JSR 223スクリプトフレームワーク(動的に型付けされた言語を対象としています)にはあまり適合しません。元の質問に答えるために、ScalaにはJavaにevalがないように、eval関数がありません。このような関数は、本質的に静的な性質を備えているため、これらの言語のどちらにとっても実際には意味がありません。

私のアドバイス:evalを必要としないようにコードを再考してください(Rubyのようにそれを持っている言語であってもめったにありません)。または、アプリケーションのこの部分でScalaを使用したくない場合があります。evalが本当に必要な場合は、JRubyを使用してみてください。JRuby、ScalaとJavaは非常にうまくメッシュ化されています。システムの一部をJavaで、一部をScalaと別の部分で、 (evalを必要とするビット)Rubyで。

50
Daniel Spiewak

それは今2011年です、そしてあなたはscala.tools.nsc.Interpreter

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

66
ninjagecko

Scalaは2.11でJSR-223の公式サポートを追加しました( https://issues.scala-lang.org/browse/SI-874 )。

したがって、Daniel Spiewakから現在受け入れられている回答で行われた考慮事項(不要な方法で再考することについて)を検討した後でもそれが必要な場合は、これが公式の代替手段になるはずです。

21
Oswaldo

scalaコードを取り、それをクラスにラップし、そのクラスをコンパイルし、リフレクションを使用して新しいインスタンスを作成し、それを呼び出すことで、「eval」をエミュレートできます。少し複雑で、 scalaコンパイラは初期化が非常に遅い(2秒程度)ですが、正常に動作します。

ここに「util-eval」と呼ばれるライブラリがあります: https://github.com/Twitter/util/

問題のコードはここにあります: https://github.com/Twitter/util/blob/master/util-eval/src/main/scala/com/Twitter/util/Eval.scala

それはこのように動作します:

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

これが良い方法かどうかはわかりませんが、toolbox.parsetoolbox.evalを使用してこの問題を解決しました

Scalaで評価を行うには、次のことを行う必要があります。

  1. Scala-reflectをインポートする

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

  1. ツールボックスからevalを使用します。
  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

いつでもscalacを使用してscala=クラスをコンパイルし、そのクラスを動的にロードできます。しかし、それはあなたが望んでいることではないと思います。

2
Kim Stebel