2016-06-29 22 views
11

Alcuni debugger consentono di aggiungere dinamicamente i punti di interruzione mentre si trovano nel debugger. Questa funzionalità è possibile in R? Un esempio:aggiungi traccia/punto di interruzione già nel browser di 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" 

Durante il debug, credo di voler andare avanti nel codice. Immagina che la funzione abbia poche centinaia di righe di codice e preferirei non passarle oltre.

Mi piacerebbe essere in grado di farlo e passare dalla linea corrente alla riga successiva successiva, ma sfortunatamente continua semplicemente fuori dalla funzione.

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

Il trace chiamata mentre nel debugger semplicemente aggiunto il punto di interruzione per la funzione originale (globale), come mostrato se chiamo subito la funzione ancora:

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

Ho provato a installare entrambi contemporaneamente (at=c(3,5)) mentre si trova all'interno del browser, ma questo semplicemente imposta quelle linee per quando esco dal debugger e richiamo di nuovo la funzione.

Immagino che questo abbia a che fare con la funzione a cui trace allega il punto di interruzione. Esaminando trace (e .TraceWithMethods), penso di aver bisogno di impostare where, ma non riesco a capire come ottenerlo per impostare un nuovo punto di interruzione/traccia sulla funzione di debug.

(L'immagine più grande è che sto risolvendo una funzione che si occupa di un flusso di dati gestito da kafka. Le mie due opzioni sono attualmente (a) riavviare la funzione con la traccia più appropriata, ma questo mi impone di eliminare e riavviare il flusso di dati o (b) andare riga per riga nel debugger, noioso quando ci sono molte centinaia di righe di codice.)

+2

Sospetto che ciò non sia direttamente possibile poiché i meccanismi di tracciamento/debug si basano sulla creazione di nuove funzioni con il debug abilitato. Quello che potresti essere in grado di fare è se la linea che vuoi saltare è di per sé una chiamata di funzione, quindi esegui il debug di quella funzione. per esempio. in '{line1; line2; line3; my_fun(); line4}' puoi eseguire 'debug (my_fun)' seguito da 'c' al prompt browse e salterai direttamente al contenuto' my_fun'. – BrodieG

+1

Grazie, questo è quello che sospetto. Il tuo suggerimento funziona se c'è una funzione al prossimo punto di interruzione. Grazie, @BrodieG. – r2evans

risposta

1

Questo può essere una sorta di soluzione. In primo luogo fare come nel tuo post:

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

Avanti, facciamo come segue nel debugger:

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" 

Il rovescio della medaglia è che si finisce indietro "line 5" nella chiamata originale per quux dopo che l'uscita dal la chiamata a this_func. Inoltre, dobbiamo tenere traccia dell'ultimo valore at. Potremmo essere in grado di ottenere questo da un'altra funzione?

+0

Molto interessante, grazie Benjamin! Ci giocherò un po 'con questo. – r2evans

+0

Felice di aiutare, se questa risposta ha risolto il problema, contrassegnarlo come accettato. –

+0

È anche uno svantaggio che questo riesegua le prime * n * linee di codice? Ad esempio, se una qualsiasi delle prime righe includesse effetti collaterali (ad es. Aggiornamenti di database), questa non sarebbe un'opzione praticabile. Trovo ancora un lavoro interessante, grazie Benjamin. – r2evans

Problemi correlati