2012-03-07 5 views
10

Ho un wrapper per l'in-built warning() funzione R che chiama in fondo warning(sprintf(...)):R avvertimento() involucro - elevare alla funzione di genitore

warningf <- function(...) 
    warning(sprintf(...)) 

Questo è perché io uso warning(sprintf(...)) così spesso che ho deciso di fare una funzione fuori di esso (è in un pacchetto che ho delle funzioni che uso spesso).

Quindi utilizzo warningf durante la scrittura di funzioni. vale a dire, invece di scrivere:

f <- function() { 
    # ... do stuff 
    warning(sprintf('I have %i bananas!',2)) 
    # ... do stuff 
} 

scrivo:

f <- function() { 
    # ... do stuff 
    warningf('I have %i bananas!',2) 
    # ... do stuff 
} 

Se chiamo il primo f(), ottengo:

Warning message: 
In f() : I have 2 bananas! 

Questo è un bene - mi dice dove l'avviso è venuto da f() e cosa è andato storto.

Se chiamo il secondo f(), ottengo:

Warning message: 
In warningf("I have %i bananas!",2) : I have 2 bananas! 

Questo non è l'ideale - mi dice l'avvertimento era in funzione warningf (ovviamente, perché è la funzione warningf che chiama warning, non f), mascherando il fatto che proveniva effettivamente dalla funzione f().

Quindi la mia domanda è: Posso in qualche modo "sollevare" la chiamata warning in modo che venga visualizzato il messaggio warning in f() anziché warning in warningf?

risposta

12

Un modo per gestire questo è ottenere un elenco degli ambienti nello stack delle chiamate e quindi incollare il nome del frame principale nel messaggio di avviso.

Si esegue questa operazione con la funzione sys.call() che restituisce un elemento nello stack di chiamate. Si desidera estrarre il secondo da ultimo elemento in questo elenco, vale a dire il genitore a warningf:

warningf <- function(...){ 
    parent.call <- sys.call(sys.nframe() - 1L) 
    warning(paste("In", parent.call, ":", sprintf(...)), call.=FALSE) 
} 

Ora, se corro vostra funzione:

> f() 
Warning message: 
In f() : I have 2 bananas! 
+0

@richiecotton grazie per la modifica. La tua strada è molto meglio. – Andrie

+0

+1 - bella risposta. Ancora più semplice sarebbe usare semplicemente 'sys.call (-1)'. (Funziona b/c l'argomento 'which' su' sys.call() 'rappresenta" il numero di frame da tornare se negativo "). –

+0

Fantastico! Ho pensato che potesse avere qualcosa a che fare con lo stack delle chiamate quando ho visto il codice 'warning', ma non sapevo come farlo. Grazie! –

Problemi correlati