2016-06-29 36 views
11

Niektóre debuggery umożliwiają dynamiczne dodawanie punktów przerwania w debugerze. Czy ta funkcja jest możliwa w R? Przykład:dodaj ślad/punkt przerwania, gdy jest już w przeglądarce 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" 

Podczas debugowania, myślę, że chcę skoczyć do przodu w kodzie. Wyobraź sobie, że funkcja ma kilkaset linii kodu, a ja wolałbym ich nie przekraczać.

Chciałbym móc to zrobić i przeskoczyć z bieżącej linii do następnej interesującej linii, ale niestety po prostu przestaje działać.

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

Wezwanie trace natomiast w debugera jedynie dodany punkt przerwania do pierwotnej funkcji (globalnej), jak pokazano gdybym natychmiast wywołać funkcję ponownie:

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

Próbowałem ustawienie obu naraz (at=c(3,5)) w przeglądarce, ale to ustawia te wiersze, kiedy wyjdę z debuggera i ponownie zadzwonię do tej funkcji.

Zgaduję, że ma to związek z funkcją, do której trace dołącza punkt przerwania. Patrząc na trace (i), myślę, że muszę ustawić where, ale nie mogę dowiedzieć się, jak uzyskać to, aby ustawić nowy punkt przerwania/śledzenia na funkcji debugowania.

(Większy obraz polega na tym, że rozwiązuję problem związany z strumieniem danych podawanym przez kafka.) Moje dwie opcje to obecnie (a) ponowne uruchomienie funkcji przy użyciu bardziej odpowiedniego śledzenia, ale wymaga to ode mnie oczyść i zrestartuj strumień danych lub (b) przejdź wiersz po linii w debugerze, żmudny, gdy jest setki linii kodu.)

+2

Podejrzewam, że nie jest to bezpośrednio możliwe, ponieważ mechanizmy śledzenia/debugowania polegają na tworzeniu nowych funkcji z włączonym debugowaniem. To, co możesz zrobić, to to, czy linia, do której chcesz przejść, jest wywołaniem funkcji, a następnie 'debugowaniem' tej funkcji. na przykład w '{line1; line2; line3; my_fun(); line4}' możesz uruchomić 'debug (my_fun)', po której następuje 'c' w monicie przeglądania, a przejdziesz od razu do zawartości' my_fun'. – BrodieG

+1

Dzięki, to jest to, co podejrzewam. Twoja sugestia działa, jeśli istnieje funkcja w następnym punkcie przerwania. Dzięki, @BrodieG. – r2evans

Odpowiedz

1

To może być swego rodzaju rozwiązanie. Najpierw zrobić jak w poście:

> 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" 

Następnie robimy w następujący debuggera:

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" 

Minusem jest to, że możemy skończyć z powrotem na "line 5" w oryginalnym wywołanie quux po naszym wyjściu z połączenie z this_func. Ponadto musimy śledzić ostatnią wartość at. Możemy być w stanie uzyskać to z innej funkcji?

+0

Bardzo interesujące, dzięki Benjamin! Pobawię się tym trochę. – r2evans

+0

Cieszę się, że pomogłem, jeśli ta odpowiedź rozwiązała Twój problem, oznacz go jako zaakceptowany. –

+0

Czy jest to również wadą, która powoduje ponowne wykonanie pierwszych * n * linii kodu? Na przykład, jeśli którykolwiek z pierwszych kilku wierszy zawierał jakiś efekt uboczny (na przykład aktualizacje bazy danych), nie byłaby to opłacalna opcja. Nadal uważam, że jest to interesująca praca, dzięki Benjamin. – r2evans