2012-03-07 963 views
10

tengo una envoltura alrededor de la warning() función incorporada en I que llama básicamente warning(sprintf(...)):R advertencia() envoltorio - elevar a la función de los padres

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

Esto es porque uso warning(sprintf(...)) tan a menudo que decidí hacer una función de eso (está en un paquete que tengo de funciones que uso a menudo).

Luego uso warningf cuando escribo funciones. es decir, en lugar de escribir:

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

escribo:

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

Si llamo a la primera f(), me sale:

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

Esto es bueno - me dice que la advertencia vino de f() y qué salió mal.

Si llamo a la segunda f(), me sale:

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

Esto no es ideal - me dice que la advertencia era en la función warningf (por supuesto, porque es la función warningf que llama warning, no f), enmascarando el hecho de que realmente proviene de la función f().

Así que mi pregunta es: ¿Puedo de alguna manera "aumentar" la llamada warning para que aparezca el mensaje warning in f() en lugar del warning in warningf?

Respuesta

12

Una forma de resolver esto es obtener una lista de los entornos en su pila de llamadas y luego pegar el nombre del fotograma principal en su advertencia.

Lo hace con la función sys.call() que devuelve un elemento en la pila de llamadas. Que desea extraer el segundo del último elemento de esta lista, es decir, el padre de warningf:

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

Ahora, si me quedo a su función:

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

@richiecotton gracias por la edición. Tu camino es mucho mejor. – Andrie

+0

+1 - buena respuesta. Incluso más simple sería usar 'sys.call (-1)'. (Funciona b/c el argumento 'which' para' sys.call() 'representa" el número de fotogramas a retroceder si es negativo "). –

+0

¡Fantástico! Pensé que podría tener algo que ver con revisar la pila de llamadas cuando miré el código de "advertencia", pero no sabía cómo hacerlo. ¡Gracias! –

Cuestiones relacionadas