Wie lade ich eine Klasse oder ein Paket in Scala REPL neu?
-
20-09-2019 - |
Frage
Ich habe fast immer eine oder zwei Scala REPL-Sitzungen geöffnet, was es sehr einfach macht, Java- oder Scala-Klassen schnell zu testen.Aber wenn ich eine Klasse ändere und sie neu kompiliere, fährt die REPL mit der geladenen alten fort.Gibt es eine Möglichkeit, die Klasse neu zu laden, anstatt die REPL neu starten zu müssen?
Um ein konkretes Beispiel zu geben: Angenommen, wir haben die Datei Test.scala:
object Test { def hello = "Hello World" }
Wir kompilieren es und starten die 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
Dann ändern wir die Quelldatei in
object Test {
def hello = "Hello World"
def goodbye = "Goodbye, Cruel World"
}
aber wir können es nicht verwenden:
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;
Lösung
Das Nachladen der Klasse ist kein einfaches Problem. Tatsächlich macht es das JVM sehr schwierig. Sie haben jedoch ein paar Optionen:
- Starten Sie die Scala Repl im Debug -Modus. Der JVM-Debugger verfügt über ein integriertes Nachladen, das auf der Methodenebene funktioniert. Es wird Ihnen bei dem von Ihnen angegebenen Fall nicht helfen, aber es würde etwas Einfaches wie die Änderung einer Methodenimplementierung behandeln.
- Verwenden Sie Jrebel (http://www.zeroturnaround.com/jrebel). Jrebel ist im Grunde genommen eine übergeladene Klassen-Nachladenlösung für das JVM. Es kann Mitglied Addition/Entfernung, neue/entfernte Klassen, Definitionsänderungen usw. verarbeiten kippen Handle ist Änderungen in der Klassenhierarchie (z. B. Hinzufügen einer Super-Schnittstelle). Es ist kein kostenloses Tool, aber sie bieten eine ergänzende Lizenz, die sich auf Scala Compilation -Einheiten beschränkt.
Leider sind beide durch die Implementierungsdetails der Scala Reples begrenzt. Ich benutze Jrebel, und es macht normalerweise den Trick, aber es gibt immer noch Fälle, in denen die Repl nicht die Reloaded -Klasse (ES) widerspiegelt. Trotzdem ist es besser als nichts.
Andere Tipps
Es gibt eine Alternative zum Nachladen der Klasse, wenn das Ziel nicht frühere Befehle wiederholen muss. Die Reply hat den Befehl
:replay
Dadurch wird die Repl -Umgebung neu gestartet und alle vorherigen gültigen Befehle zurückgegeben. (Die Ungültigen werden übersprungen. Wenn es also vorher falsch war, funktioniert es nicht plötzlich.) Wenn die Reples zurückgesetzt wird, laden Sie Klassen neu, sodass neue Befehle den Inhalt neuer Klassen verwenden können (tatsächlich die alten Befehle wird auch diese neu kompilierten Klassen verwenden).
Dies ist keine allgemeine Lösung, sondern eine nützliche Abkürzung, um eine individuelle Sitzung mit einem erneuten Zustand zu erweitern.
Hinweis: Dies gilt für die bare Scala Repl. Wenn Sie es aus SBT oder einer anderen Umgebung ausführen, kann dies abhängig von der Art und Weise, wie SBT oder die anderen Umgebungsklassen paket, oder nicht, wenn Sie nicht aktualisieren, was sich auf dem tatsächlichen Klassenpfad befindet, natürlich gewonnen hat. Ich arbeite!
Es gibt einen Befehl, der Sie erfolgt
:load path/to/file.scala
Dies lädt die Scala -Quelldatei neu und wird in Klassen neu kompiliert. Dann können Sie Ihren Code wiederholen
Das funktioniert bei mir....
Wenn Ihre neue Quelldatei Test.scala
sieht ungefähr so aus...
package com.tests
object Test {
def hello = "Hello World"
def goodbye = "Goodbye, Cruel World"
}
Sie müssen die neuen Änderungen zunächst in die Scala-Konsole (REPL) laden.
:load src/main/scala/com/tests/examples/Test.scala
Importieren Sie dann das Paket erneut, damit Sie in der Scala-Konsole auf den neuen Code verweisen können.
import com.tests.Test
Genießen Sie jetzt Ihren neuen Code, ohne Ihre Sitzung neu zu starten :)
scala> Test.goodbye
res0: String = Goodbye, Cruel World
Wenn sich die .scala -Datei im Verzeichnis befindet, in dem Sie mit der Replin beginnen, können Sie den vollständigen Pfad begeben, einfach setzen :load myfile.scala
, und dann importieren.