R warning() wrapper - повысить до родительской функции
У меня есть обертка вокруг встроенной функции 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
?
Ответы
Ответ 1
Один из способов справиться с этим - получить список сред в вашем стеке вызовов, а затем вставить имя родительского фрейма в ваше предупреждение.
Это sys.call()
с помощью функции sys.call()
которая возвращает элемент в стек вызовов. Вы хотите извлечь второй из последнего элемента в этом списке, то есть родительский warningf
для 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!
Позднее edit: deparse(parent.call)
преобразует вызов в строку в случае, если функция f()
имеет аргументы, и показывает вызов в том виде, в котором он был указан (т.е. включает аргументы и т.д.).
Ответ 2
Я знаю его старый, но sys.call(sys.nframe() - 1L)
или sys.call(-1)
возвращает вектор с именем функции и аргументом. Если вы используете его внутри paste()
оно выдаст два предупреждения, одно из функции и одно из аргумента. Ответ не отображается, потому что f()
не имеет аргументов.
sys.call(sys.nframe() - 1L)[1]
.