Подтвердить что ты не робот

Добавить трассировку/точку останова, находясь в браузере R

Редактировать: для записи принятый ответ имеет существенный недостаток в том, что он повторно выполняет первые n строк кода в функции при повторной отладке. Это может быть хорошо, но когда эти строки кода включают побочные эффекты (например, обновления базы данных) и/или длительные вычисления, становится очевидным, что происходит. Я не верю, что R предоставляет возможность делать это "правильно" (как это делают некоторые другие языки). Облом.


Некоторые отладчики позволяют динамически добавлять точки останова, находясь в отладчике. Возможна ли эта функциональность в R? Пример:

quux <- function(..)
{ # line 1
  "line 2"
  "line 3"
  "line 4"
  "line 5"
  "line 6"
}

trace("quux", tracer = browser, at = 3)
# [1] "quux"
quux()
# Tracing quux() step 3 
# Called from: eval(expr, envir, enclos)
# Browse[1]> 
# debug: [1] "line 3"

Во время отладки я верю, что хочу ускорить выполнение кода. Представьте, что функция имеет несколько сотен строк кода, и я предпочел бы не проходить через них.

Я хотел бы иметь возможность сделать это и перейти от текущей строки к следующей интересной строке, но, к сожалению, она просто выходит из функции.

# Browse[2]>
trace("quux", tracer = browser, at = 5)
# [1] "quux"
# Browse[2]>
c    
# [1] "line 6"
# # (out of the debugger)

Вызов trace в отладчике просто добавил точку останова к исходной (глобальной) функции, как показано, если я немедленно вызову функцию снова:

quux()
# Tracing quux() step 5 
# Called from: eval(expr, envir, enclos)
# Browse[1]> 
# debug: [1] "line 5"

Я попытался установить оба сразу (at=c(3,5)) в браузере, но это просто устанавливает эти строки, когда я выхожу из отладчика и снова вызываю функцию.

Я предполагаю, что это связано с функцией, к которой trace прикрепляет точку останова. Рассматривая trace.TraceWithMethods), я думаю, что мне нужно установить where, но я не могу понять, как заставить его установить новую точку останова/трассировки в функции отладки.

(Более общая картина состоит в том, что я устраняю неисправность функции, имеющей дело с потоком данных под руководством Кафки. В настоящее время у меня есть два варианта: (а) перезапустить функцию с более подходящей трассировкой, но это требует от меня очистки и перезапуска поток данных, а также (b) построчно переходить в отладчик, утомительно, когда в коде много сотен строк.)

4b9b3361

Ответ 1

Это может быть своего рода решение. Сначала сделайте так, как в своем посте:

> quux <- function(..)
+ { # line 1
+   x <- 1   # added for illustration
+   "line 3"
+   "line 4"
+   "line 5"
+   print(x) # added for illustration
+   "line 7"
+   "line 8"
+ }
> 
> trace("quux", tracer = browser, at = 4)
[1] "quux"
> quux()
Tracing quux() step 4 
Called from: eval(expr, p)
Browse[1]> n
debug: [1] "line 4"

Далее в отладчике мы делаем следующее:

Browse[2]> this_func <- eval(match.call()[[1]])       # find out which funcion is called
Browse[2]> formals(this_func) <- list()               # remove arguments
Browse[2]> body(this_func) <- body(this_func)[-(2:4)] # remove lines we have evalutaed   
Browse[2]> trace("this_func", tracer = browser, 
+                at = 8 - 4 + 1)                      # at new line - old trace point
Tracing function "this_func" in package "base"
[1] "this_func"
Browse[2]> this_func                                  # print for illustration
function () 
{
    "line 5"
    print(x)
    "line 7"
    "line 8"
}
Browse[2]> environment(this_func) <- environment()    # change enviroment so x is present
Browse[2]> this_func()                                # call this_func
[1] 1
[1] "line 8"

Недостатком является то, что мы вернемся к "line 5" в исходном вызове quux после выхода из вызова this_func. Кроме того, мы должны отслеживать последнее значение at. Мы можем получить это от другой функции?