12 Stimmen

R warnung() Wrapper - an übergeordnete Funktion weitergeben

Ich habe einen Wrapper um die integrierte warning()-Funktion in R, die im Grunde warning(sprintf(...)) aufruft:

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

Das liegt daran, dass ich warning(sprintf(...)) so oft benutze, dass ich beschlossen habe, eine Funktion daraus zu machen (es ist in einem Paket von Funktionen, die ich oft benutze).

Dann benutze ich warningf, wenn ich Funktionen schreibe. Also schreibe ich anstatt:

f <- function() {
    # ... mache Sachen
    warning(sprintf('Ich habe %i Bananen!',2))
    # ... mache Sachen
}

schreibe ich:

f <- function() {
    # ... mache Sachen
    warningf('Ich habe %i Bananen!',2)
    # ... mache Sachen
}

Wenn ich die erste f() aufrufe, bekomme ich:

Warnmeldung:
In f() : Ich habe 2 Bananen!

Dies ist gut - es sagt mir, woher die Warnung von f() kommt und was schief gelaufen ist.

Wenn ich die zweite f() aufrufe, bekomme ich:

Warnmeldung:
In warningf("Ich habe %i Bananen!",2) : Ich habe 2 Bananen!

Dies ist nicht ideal - es sagt mir, dass die Warnung in der warningf-Funktion war (natürlich, weil es die warningf-Funktion ist, die warning aufruft, nicht f), und verdeckt die Tatsache, dass sie tatsächlich aus der f()-Funktion stammt.

Also meine Frage ist: Kann ich irgendwie den warning-Aufruf "höherstufen", damit er die Warnung in f()-Nachricht anzeigt anstatt die Warnung in warningf?

16voto

Andrie Punkte 169813

Ein Weg, damit umzugehen, besteht darin, eine Liste der Umgebungen im Aufrufstapel zu erhalten und dann den Namen des übergeordneten Rahmens in Ihrer Warnung einzufügen.

Dies können Sie mit der Funktion sys.call() tun, die ein Element im Aufrufstapel zurückgibt. Sie möchten das zweite Element von hinten in dieser Liste extrahieren, d.h. den Elternrahmen zu warningf:

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

Jetzt, wenn ich Ihre Funktion ausführe:

> f()
Warnmeldung:
In f() : Ich habe 2 Bananen! 

Spätere Bearbeitung : deparse(parent.call) wandelt den Aufruf in einen String um im Fall, dass die Funktion f() Argumente hatte, und zeigt den Aufruf so, wie er angegeben wurde (inklusive Argumente usw.).

-1voto

Ich weiß, es ist alt, aber sys.call(sys.nframe() - 1L) oder sys.call(-1) gibt einen Vektor zurück, mit dem Funktionsnamen und dem Argument. Wenn Sie es innerhalb von paste() verwenden, werden zwei Warnungen ausgegeben, eine von der Funktion und eine vom Argument. Die Antwort wird nicht angezeigt, weil f() keine Argumente hat.
sys.call(sys.nframe() - 1L)[1] macht den Trick.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X