Как перезагрузить класс или пакет в Scala REPL? - PullRequest
43 голосов
/ 18 марта 2010

У меня почти всегда открыт один или два сеанса Scala REPL, что позволяет очень быстро провести классы Java или Scala. Но если я изменяю класс и перекомпилирую его, REPL продолжается с загруженным старым. Есть ли способ заставить его перезагрузить класс, вместо того, чтобы перезапускать REPL?

Просто чтобы привести конкретный пример, предположим, у нас есть файл Test.scala:

object Test { def hello = "Hello World" }

Скомпилируем и запустим REPL:

~/pkg/scala-2.8.0.Beta1-prerelease$ bin/scala
Welcome to Scala version 2.8.0.Beta1-prerelease
(Java HotSpot(TM) Server VM, Java 1.6.0_16).
Type in expressions to have them evaluated.
Type :help for more information.

scala> Test.hello
res0: java.lang.String = Hello World

Затем мы меняем исходный файл на

object Test {
  def hello = "Hello World"
  def goodbye = "Goodbye, Cruel World"
}

но мы не можем его использовать:

scala> Test.goodbye
<console>:5: error: value goodbye is not a member of object Test
       Test.goodbye
            ^

scala> import Test;
<console>:1: error: '.' expected but ';' found.
       import Test;

Ответы [ 5 ]

40 голосов
/ 19 марта 2010

Существует альтернатива перезагрузке класса, если цель состоит в том, чтобы не повторять предыдущие команды. REPL имеет команду

:replay

, который перезапускает среду REPL и воспроизводит все предыдущие действительные команды. (Недопустимые из них пропускаются, поэтому, если раньше они были неправильными, они не будут работать внезапно.) Когда REPL сбрасывается, он перезагружает классы, поэтому новые команды могут использовать содержимое перекомпилированных классов (фактически, старые команды также будет использовать эти перекомпилированные классы).

Это не общее решение, но полезный ярлык для расширения отдельного сеанса с перевычисляемым состоянием.

Примечание: это относится к чистому REPL Scala. Если вы запускаете его из SBT или какой-либо другой среды, он может работать или не работать в зависимости от того, как SBT или другая среда упаковывает классы - если вы не обновите то, что находится на фактическом используемом пути к классам, конечно, он выиграл ' т работа!

27 голосов
/ 18 марта 2010

Перегрузка классов не является легкой проблемой. На самом деле, это то, что JVM делает очень сложно. У вас есть несколько вариантов:

  • Запустите Scala REPL в режиме отладки. Отладчик JVM имеет встроенную перезагрузку, которая работает на уровне методов. Это не поможет вам в случае, который вы привели, но справится с чем-то простым, например, с изменением реализации метода.
  • Использовать JRebel (http://www.zeroturnaround.com/jrebel). JRebel - это в основном решение для перезарядки классов с JVM. Он может справиться добавление / удаление членов, новые / удаленные классы, изменения определений и т. д. Почти единственное, что не может обработать , - это изменения в иерархии классов (добавление суперинтерфейса, для пример). Это не бесплатный инструмент, но они предлагают дополнительную лицензию, ограниченную единицами компиляции Scala.

К сожалению, оба они ограничены деталями реализации Scala REPL. Я использую JRebel, и он обычно делает свое дело, но все еще есть случаи, когда REPL не будет отражать перезагруженный класс (ы). Тем не менее, это лучше, чем ничего.

8 голосов
/ 26 сентября 2014

Есть команда, отвечающая вашим требованиям

:load path/to/file.scala

, который перезагрузит исходный файл scala и перекомпилируется в классы, затем вы можете воспроизвести свой код

6 голосов
/ 27 сентября 2014

Это работает для меня ....

Если ваш новый исходный файл Test.scala выглядит примерно так ...

package com.tests

object Test {
  def hello = "Hello World"
  def goodbye = "Goodbye, Cruel World"
}

Сначала вы должны загрузить новые изменения в консоль Scala (REPL).

:load src/main/scala/com/tests/examples/Test.scala

Затем повторно импортируйте пакет, чтобы вы могли ссылаться на новый код в консоли Scala.

import com.tests.Test

Теперь наслаждайтесь новым кодом, не перезапуская сеанс:)

scala> Test.goodbye
res0: String = Goodbye, Cruel World
2 голосов
/ 07 октября 2015

Если файл .scala находится в каталоге, где вы запускаете REPL, вы можете пропустить полный путь, просто введите :load myfile.scala, а затем импортируйте.

...