在任意Scala代码定位期间放入解释器


84

我来自Python背景,在我的代码中的任何时候都可以添加

import pdb; pdb.set_trace()

在运行时,我将在那个位置进入交互式解释器。scala是否具有等效功能,或者在运行时无法实现?


7
本着“广告中的真相”的精神,Scala没有口译员。它的REPL是“编译即用”。也就是说,如果您愿意,REPL代码(包括编译器)可以合并到您的应用程序中(如下所示)
Randall Schulz 2010年

1
但是,除了您明确且费力地绑定到REPL启动代码中的内容之外,REPL会在不了解您的运行上下文的情况下启动。见下文。我认为在python中,您可以进入运行上下文,这要好得多。无论如何,stackoverflow.com/questions/24674288/…是最新的。
matanster 2014年

Answers:


78

是的,您可以在Scala 2.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

您也可以通过调用break接收的ListDebugParam而不是vararg ,无条件地进入REPL 。这是完整的示例,代码和执行:

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
这可能会导致scala.tools.nsc.MissingRequirementError: object scala not found.Scala 2.8中的错误。您可能需要宿主进程的类路径明确地传递给Scalac的设置,但breakbreakIf没有这样做。下面是一个补丁版本break,它:gist.github.com/290632
返璞词

@retronym有趣,它只在这里起作用。发送给paulp。他提到这件事将要改变。
Daniel C. Sobral

我从IntelliJ运行的JUnit测试中进行了尝试。IntelliJ使用发起了该过程java -classpath ...。我想如果您使用scala -classpath它会更好。
Retronym 2010年

4
它是模块的依赖项,因此是类路径的依赖项。2.8未通过的内容java -classpath:主机进程为scalac设置的old.nabble.com/...
返璞词



24

IntelliJ IDEA:

  1. 以调试模式运行或附加远程调试器
  2. 设置一个断点并运行直到到达断点
  3. 打开Evaluate ExpressionAlt+ F8,在菜单中:运行->评估表达式)窗口以运行任意Scala代码。
  4. 输入要运行的代码片段或表达式,然后单击评估
  5. 输入Alt+V或单击“评估”以运行代码片段。

蚀:

作为斯卡拉2.10两者breakbreakIf已经从删除ILoop

要进入口译员的行列,您将不得不ILoop直接与之合作。

首先添加scala compiler库。对于Eclipse Scala,右键单击project => 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
那太糟了。:(
Daniel C. Sobral

@Daniel为什么这么恐怖?
哈卡(Hakkar),

14
因为它增加了很多样板,而这些样板与程序中某个点的调试目标完全无关,而是与使REPL运行的机制有关。
Daniel C. Sobral

1
@Daniel在scala 2.10中还有更好的方法吗?
roterl 2014年

@roterl上面的问题是什么?
Daniel C. Sobral 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.