2010-01-29 16 views
77

我来自一个Python的背景,在此,我的代码中的任何一点,我可以添加拖放到任意解释Scala代码位置时

import pdb; pdb.set_trace() 

,并在运行时,我会在那个点被放入一个交互式解释。有scala的等价物,还是在运行时不可能?

+7

在精神“广告真相”,斯卡拉没有翻译。它的REPL是“编译并行”。也就是说,如果您愿意,可以将REPL代码(包括编译器)合并到您的应用程序中(如下所示) – 2010-01-29 15:41:11

+1

但是,REPL将在没有任何运行环境知识的情况下启动,除非您在REPL中明确且费力地绑定了 - 启动代码。见下文。我认为,在python中,你进入了更好的运行环境。无论如何,http://stackoverflow.com/questions/24674288/clean-solution-for-dropping-into-repl-console-in-the-middle-of-program-execution?lq=1是最新的。 – matanster 2014-09-06 17:11:06

回答

75

是的,你可以,在斯卡拉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无条件投入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

这可能会导致scala 2.8中出现scala.tools.nsc.MissingRequirementError:object scala not found错误。您可能需要将主机进程的类路径显式传递给Scalac的设置,但“break”和“breakIf”不会执行此操作。这里有一个修补版本的'break':http://gist.github.com/290632 – retronym 2010-01-30 17:14:15

+0

@retronym有趣的是,它只是在这里工作。发送给paulp。他提到这件事情将会改变。 – 2010-01-30 18:37:04

+0

我从IntelliJ运行的JUnit测试中试过了。 IntelliJ使用'java -classpath ...'启动了这个过程。我猜如果你使用'scala -classpath'而不是它会工作的很好。 – retronym 2010-01-30 18:48:41

24

要添加到丹尼尔的回答,为斯卡拉2.9中,breakbreakIf方法都包含在scala.tools.nsc.interpreter.ILoop。另外,DebugParam现在是NamedParam

+0

您需要添加[jline](http://mvnrepository.com/artifact/org.scala-lang/jline/2.9.1)作为依赖项。 – schmmd 2011-12-09 01:47:45

+8

你可以写一个新的用法的例子吗? – Will 2013-04-23 22:03:37

23

的IntelliJ IDEA:

  1. 在调试模式下运行或连接远程调试器
  2. 设置断点并运行,直到达到它
  3. 打开Evaluate ExpressionAlt键 + F8,在菜单中:运行 - >评估表达式)窗口运行任意的Scala代码。要运行并点击评估
  4. 类型Alt键 + V或点击评估运行的代码片段是什么代码片段或表达
  5. 类型。

蚀:

作为斯卡拉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斯卡拉解释器可以从Console视图中使用:

+17

太可怕了。 :( – 2013-10-28 17:50:31

+0

@Daniel为什么会这么糟糕? – Hakkar 2013-10-28 19:08:13

+12

因为它增加了很多与程序中某个点的调试目标完全无关的锅炉板,而是与获取REPL的机制有关。 – 2013-10-29 00:48:13