任意のscalaコードの場所でインタープリターにドロップする


84

私はPythonのバックグラウンドを持っており、コードの任意の時点で追加できます

import pdb; pdb.set_trace()

そして実行時に、私はその場所でインタラクティブなインタプリタにドロップされます。Scalaに相当するものはありますか、それとも実行時にこれは不可能ですか?


7
「広告の真実」の精神で、Scalaには通訳がいません。そのREPLは「コンパイルアンドゴー」です。とはいえ、必要に応じて、REPLコード(コンパイラーを含む)をアプリケーションに組み込むことができます(以下を参照)
Randall Schulz

1
ただし、REPLは、REPL起動コードで明示的かつ手間をかけてバインドしたものを除いて、実行コンテキストの知識がなくても起動します。下記参照。Pythonでは、実行中のコンテキストにたどり着くと思います。これははるかに優れています。とにかく、stackoverflow.com / questions / 24674288 /…はより最新です。
マタンスター2014

回答:


78

はい、できます。Scala2.8で。これが機能するためには、クラスパスにscala-compiler.jarを含める必要があることに注意してください。を使用してscalaプログラムを呼び出すとscala、自動的に実行されます(または、私が行ったテストではそう思われます)。

その後、次のように使用できます。

import scala.tools.nsc.Interpreter._

object TestDebugger {
  def main(args: Array[String]) {
    0 to 10 foreach { i =>
      breakIf(i == 5, DebugParam("i", i))
      println(i)
    }
  }
}

複数のDebugParam引数を渡すことができます。REPLが表示されると、右側の値は、左側で指定した名前のvalにバインドされます。たとえば、その行を次のように変更すると、次のようになります。

      breakIf(i == 5, DebugParam("j", i))

次に、実行は次のように行われます。

C:\Users\Daniel\Documents\Scala\Programas>scala TestDebugger
0
1
2
3
4
j: Int

scala> j
res0: Int = 5

を入力して実行を続行します:quit

varargの代わりにのbreakを受け取るを呼び出すことによって無条件にREPLにドロップすることもできます。完全な例、コード、および実行は次のとおりです。ListDebugParam

import scala.tools.nsc.Interpreter._

object TestDebugger {
  def main(args: Array[String]) {
    0 to 10 foreach { i =>
      breakIf(i == 5, DebugParam("j", i))
      println(i)
      if (i == 7) break(Nil)
    }
  }
}

その後:

C:\Users\Daniel\Documents\Scala\Programas>scalac TestDebugger.scala

C:\Users\Daniel\Documents\Scala\Programas>scala TestDebugger
0
1
2
3
4
j: Int

scala> j
res0: Int = 5

scala> :quit
5
6
7

scala> j
<console>:5: error: not found: value j
       j
       ^

scala> :quit
8
9
10

C:\Users\Daniel\Documents\Scala\Programas>

3
これにより、Scala2.8scala.tools.nsc.MissingRequirementError: object scala not found.でエラーが発生する可能性があります。あなたは明示的にScalacの設定をホストプロセスのクラスパスを渡す必要があるかもしれませんが、breakおよびbreakIfこれをしません。パッチを当てたバージョンbreakは次のとおり
レトロニム

@retronymおかしい、それはここでうまくいった。ポールプに送ってください。彼は、このことはとにかく変更されるだろうと述べました。
ダニエルC.ソブラル2010年

IntelliJが実行するJUnitテストから試してみました。IntelliJはでプロセスを開始しましたjava -classpath ...scala -classpath代わりに使用すればうまくいくと思います。
レトロニム2010年

4
これはモジュールの依存関係であり、したがってクラスパスにあります。2.8はjava -classpath、ホストプロセスの内容をscalacの設定に渡しません:old.nabble.com/…–
レトロニム


24

ダニエルの答えに追加するために、Scala 2.9以降、メソッドbreakbreakIfメソッドはに含まれていscala.tools.nsc.interpreter.ILoopます。また、DebugParamNamedParamです。


依存関係としてjlineを追加する必要があります。
schmmd 2011

8
新しい使い方の例を書いていただけませんか?
ウィル

24

IntelliJ IDEA:

  1. デバッグモードで実行するか、リモートデバッガーを接続します
  2. ブレークポイントを設定し、到達するまで実行します
  3. Evaluate ExpressionAlt+ F8、メニュー内:実行->式の評価)ウィンドウを開いて、任意のScalaコードを実行します。
  4. 実行するコードフラグメントまたは式を入力し、[評価]をクリックします
  5. Alt+と入力するVか、[評価]をクリックしてコードフラグメントを実行します。

Eclipse:

Scalaの2.10のとおり両方breakbreakIfから削除されましたILoop

通訳に侵入するには、ILoop直接作業する必要があります。

最初にscala compilerライブラリを追加します。Eclipse Scalaの場合、プロジェクトを右クリック=> Build Path=> Add Libraries...=> Scala Compiler

そして、インタプリタを開始する場所で次を使用できます。

import scala.tools.nsc.interpreter.ILoop
import scala.tools.nsc.interpreter.SimpleReader
import scala.tools.nsc.Settings

val repl = new ILoop
repl.settings = new Settings
repl.settings.Yreplsync.value = true
repl.in = SimpleReader()
repl.createInterpreter()

// bind any local variables that you want to have access to
repl.intp.bind("row", "Int", row)
repl.intp.bind("col", "Int", col)

// start the interpreter and then close it after you :quit
repl.loop()
repl.closeInterpreter()

Eclipse Scalaでは、インタープリターは次のConsoleビューから使用できます。


18
それは恐ろしいです。:(
ダニエルC.ソブラル2013年

@ダニエルなぜそれは恐ろしいのですか?
ハッカー2013年

14
これは、プログラムのある時点でのデバッグの目標とはまったく関係がなく、代わりにREPLを実行するメカニズムに関係する多くのボイラープレートを追加するためです。
ダニエルC.ソブラル2013年

1
@Danielはscala2.10にもっと良い方法はありますか?
roterl 2014年

@roterl上記の問題は何ですか?
ダニエルC.ソブラル2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.