"Эвал" в Скала

Можно ли использовать Scala для написания скриптов в Java-приложении?

Мне нужно загрузить фрагмент кода Scala из Java, настроить для него область выполнения (данные, предоставляемые хост-приложением), оценить его и извлечь из него объект результата.

Документация Scala показывает, как легко вызывать скомпилированный код Scala из Java (потому что он превращается в обычный байт-код JVM).

Но как я могу оценить выражение Scala на лету (из Java или, если проще, изнутри Scala)?

Для многих других языков есть интерфейс javax.scripting. Похоже, что Scala его не поддерживает, и я не смог найти в документах по совместимости Java/Scala ничего, что не основывалось бы на преждевременной компиляции.

6 ответов

Решение

Scala не является языком сценариев. Он может выглядеть как язык сценариев, и люди могут защищать его для этой цели, но он не очень хорошо вписывается в среду сценариев JSR 223 (которая ориентирована на динамически типизированные языки). Чтобы ответить на ваш оригинальный вопрос, у Scala нет eval функция так же, как Java не имеет eval, Такая функция не имеет смысла ни для одного из этих языков, учитывая их статическую природу.

Мой совет: переосмыслите свой код так, чтобы он вам не понадобился eval (Вы делаете это редко, даже на языках, где он есть, например на Ruby). В качестве альтернативы, возможно, вы вообще не хотите использовать Scala для этой части вашего приложения. Если вам действительно нужно evalпопробуйте использовать JRuby. JRuby, Scala и Java очень хорошо сочетаются друг с другом. Довольно легко иметь часть вашей системы в Java, часть в Scala и другую часть (часть, которая требует evalв руби.

Сейчас 2011 год, и вы можете сделать это с scala.tools.nsc.Interpreter

см. http://blog.darevay.com/2009/01/remedial-scala-interpreting-scala-from-scala/

Scala добавил официальную поддержку JSR-223 в версии 2.11 ( https://issues.scala-lang.org/browse/SI-874).

Так что, если вам все еще это нужно, подумав о соображениях, изложенных в принятом в настоящее время ответе Даниэля Спевака (о переосмыслении таким образом, который не нужен), это должна быть официальная альтернатива.

Вы можете эмулировать "eval", взяв код scala, обернув его в класс, скомпилировав этот класс, используя отражение для создания нового экземпляра, а затем вызвав его. Это немного запутанно, и компилятор 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

Я не уверен, если это хороший способ, но я решил эту проблему с помощью toolbox.parse а также toolbox.eval

Чтобы получить оценку в Scala, вы должны:

  1. Импорт скала-рефлекса

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

Вы всегда можете использовать scalac для компиляции класса scala, а затем динамически загружать этот класс. Но я думаю, что это не то, что вы после.

Другие вопросы по тегам