web-dev-qa-db-ja.com

Scala REPLでクラスまたはパッケージをリロードする方法は?

私はほとんどの場合、Scala REPLセッションを1つか2つ開いているので、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;
45
Rex Kerr

クラスのリロードは簡単な問題ではありません。実際、これはJVMが非常に困難にしていることです。ただし、いくつかのオプションがあります。

  • Scala REPLをデバッグモードで開始します。JVMデバッガーには、メソッドレベルで機能するリロードが組み込まれています。これは役に立ちません。あなたが与えたケースですが、メソッドの実装を変更するような単純なものを処理します。
  • JRebelを使用します( http://www.zeroturnaround.com/jrebel )。 JRebelは基本的に、JVM用のスーパーチャージされたクラスリロードソリューションです。メンバーの追加/削除、新しい/削除されたクラス、定義の変更などを処理できます。処理できないクラスの変更だけです。階層(たとえば、スーパーインターフェイスの追加)。これは無料のツールではありませんが、Scalaコンパイル単位に制限された補完的なライセンスを提供します。

残念ながら、これらは両方ともScala REPLの実装の詳細によって制限されます。私はJRebelを使用し、通常はそれでうまくいきますが、REPL =リロードされたクラスは反映されません。それでも、何もないよりはましです。

30
Daniel Spiewak

目標が前のコマンドを繰り返す必要がないことである場合、クラスをリロードする代わりの方法があります。 REPLにはコマンドがあります

:replay

REPL環境を再起動し、以前のすべての有効なコマンドを再生します。 (無効なものはスキップされるため、以前に間違っていた場合、突然機能しません。)REPLがリセットされると、クラスがリロードされるため、新しいコマンドは再コンパイルされたクラスの内容を使用できます(実際には、古いコマンドもそれらの再コンパイルされたクラスを使用します)。

これは一般的な解決策ではありませんが、個々のセッションを再計算可能な状態で拡張するための便利なショートカットです。

注:これは、ベアScala REPLに適用されます。 SBTまたは他の環境から実行する場合、SBTまたは他の環境がクラスをパッケージ化する方法に応じて、機能する場合と機能しない場合があります。実際に使用されているクラスパスにあるものを更新しないと、もちろん機能します。仕事!

41
Rex Kerr

要件を満たすコマンドがあります

:load path/to/file.scala

scalaソースファイルをリロードしてクラスに再コンパイルすると、コードを再生できます

8
jiahut

これは私のために働きます....

新しいソースファイルの場合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
6
cevaris

.scalaファイルがREPL)を開始するディレクトリにある場合は、フルパスを省略して、:load myfile.scalaを入力してからインポートすることができます。

2
Ignacio