Загляньте в інтерпретатор під час довільного розташування коду Scala


84

Я походжу з фону Python, де в будь-який момент мого коду я можу додати

import pdb; pdb.set_trace()

і під час роботи мене в цьому місці помістять до інтерактивного перекладача. Чи існує еквівалент для Scala, або це неможливо під час виконання?


7
У дусі "правди в рекламі" Scala не має перекладача. Її REPL - "компіляція і робота". Тим не менше, код REPL (включаючи компілятор) може бути включений у вашу програму, якщо ви цього бажаєте (як показано нижче)
Randall Schulz

1
Але REPL запускатиметься без будь-якого знання вашого запущеного контексту, за винятком того, що ви чітко та копітко прив'язуєте у своєму коді запуску REPL. Дивіться нижче. Я думаю, що в python ви потрапляєте в запущений контекст, що набагато краще. так чи інакше, stackoverflow.com/questions/24674288/… є більш сучасним.
matanster

Відповіді:


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 з’явиться, значення праворуч буде пов’язане з валом, ім’я якого ви вказали зліва. Наприклад, якщо я зміню цей рядок так:

      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, який отримує Listз DebugParamзамість vararg. Ось повний приклад, код та виконання:

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, але breakі breakIfне робити цього. Ось виправлена ​​версія breakцього: gist.github.com/290632
ретронім

@retronym Смішно, тут це просто працювало. Надішліть це в бік. Він зазначив, що це все одно буде змінено.
Daniel C. Sobral

Я спробував це за допомогою тесту JUnit, запущеного IntelliJ. IntelliJ запустив процес з java -classpath .... Я думаю, якщо ви використовуєте scala -classpathзамість цього, це буде працювати нормально.
ретронім

4
Це була залежність модуля, а отже, і до шляху до класу. 2.8 не передає вміст java -classpathхост-процесу до налаштувань Scalac: old.nabble.com/…
ретронім


24

Щоб додати відповідь Даніеля, станом на Scala 2.9, методи breakand breakIfмістяться в scala.tools.nsc.interpreter.ILoop. Також DebugParamзараз NamedParam.


Вам потрібно буде додати jline як залежність.
schmmd

8
Ви можете написати приклад із новим використанням?
Буде

24

IntelliJ IDEA:

  1. Запустіть у режимі налагодження або підключіть віддалений налагоджувач
  2. Встановіть точку зупинки і біжіть, поки не дійдете до неї
  3. Відкрити Evaluate Expression( Alt+F8 вікно , у меню: Виконати -> Оцінити вираз), щоб запустити довільний код Scala.
  4. Введіть фрагмент коду або вираз, який ви хочете запустити, і натисніть кнопку Оцінити
  5. Введіть Alt+ Vабо натисніть «Оцінити», щоб запустити фрагмент коду.

Затьмарення:

Станом на Scala 2.10 обидва breakі breakIfбули вилучені з 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

@ Даніель Чому це жахливо?
Hakkar

14
Тому що він додає багато котлів, що абсолютно не пов’язано з метою налагодження в певний момент програми, і, натомість, пов’язане з механікою запуску REPL.
Daniel C. Sobral

1
@Daniel чи є якийсь кращий спосіб у Scala 2.10?
roterl

@roterl У чому проблема вищезазначеного?
Даніель К. Собрал,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.