Оболочка предупреждений R - PullRequest
11 голосов
/ 07 марта 2012

У меня есть оболочка для встроенной функции warning() в R, которая в основном вызывает warning(sprintf(...)):

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

Это потому, что я использую warning(sprintf(...)) так часто, что я решил сделатьфункции из него (это в пакете, у меня есть функции, которые я часто использую).

Затем я использую warningf, когда пишу функции.т.е. вместо того, чтобы писать:

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

Я пишу:

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

Если я позвоню первым f(), я получу:

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

Этохорошо - он говорит мне, откуда пришло предупреждение f() и что пошло не так.

Если я позвоню второму f(), я получу:

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

Это не идеально -он говорит мне, что предупреждение было в функции warningf (конечно, потому что это функция warningf, которая вызывает warning, а не f), маскируя тот факт, что оно на самом деле пришло из функции f().

Итак, мой вопрос: можно ли как-нибудь «поднять» вызов warning, чтобы он отображал сообщение warning in f() вместо warning in warningf?

Ответы [ 2 ]

13 голосов
/ 07 марта 2012

Один из способов справиться с этим - получить список сред в вашем стеке вызовов, а затем вставить имя родительского фрейма в ваше предупреждение.

Это делается с помощью функции sys.call(), которая возвращает элемент в стек вызовов. Вы хотите извлечь второй из последнего элемента в этом списке, то есть родительский элемент для warningf:

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

Теперь, если я запускаю вашу функцию:

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

Позднее редактирование: deparse(parent.call) преобразует вызов в строку в случае, если функция f() имеет аргументы, и показывает вызов в том виде, в котором он был указан (т.е. включает аргументы и т. Д.).

0 голосов
/ 10 апреля 2019

Я знаю, что он старый, но sys.call(sys.nframe() - 1L) или sys.call(-1) возвращает вектор с именем функции и аргументом.Если вы используете его внутри paste(), оно выдаст два предупреждения, одно из функции и одно из аргумента.Ответ не отображается, потому что f() не имеет аргументов.
sys.call(sys.nframe() - 1L)[1] добивается цели.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...