У меня есть несколько пользовательских логических функций, которые являются расширениями cat
. Основным примером является примерно следующее:
catt<-function(..., file = "", sep = " ", fill = FALSE, labels = NULL,
append = FALSE)
{
cat(..., format(Sys.time(), "(%Y-%m-%d %H:%M:%S)"), "\n", file = file,
sep = sep, fill = fill, labels = labels, append = append)
}
Теперь я много работаю с (самонастраиваемыми) функциями и использую некоторые из этих logfuntions, чтобы увидеть прогресс, который работает достаточно хорошо. Однако я заметил, что почти всегда использую эти функции следующим образом:
somefunc<-function(blabla)
{
catt("somefunc: start")
#do some very useful stuff here
catt("somefunc: some time later")
#even more useful stuff
catt("somefunc: the end")
}
Обратите внимание, как каждый вызов catt
начинается с имени вызываемой функции. Очень аккуратно, пока я не начну реорганизовывать свой код и переименовывать функции и т.д.
Благодаря старому списку R-списка от Брайана Рипли, если я не ошибаюсь, я нашел этот код для получения "текущего имени функции":
catw<-function(..., file = "", sep = " ", fill = FALSE, labels = NULL,
append = FALSE)
{
curcall<-sys.call(sys.parent(n=1))
prefix<-paste(match.call(call=curcall)[[1]], ":", sep="")
cat(prefix, ..., format(Sys.time(), "(%Y-%m-%d %H:%M:%S)"), "\n",
file = file, sep = sep, fill = fill, labels = labels, append = append)
}
Это очень приятно, но это не всегда работает, потому что:
- мои функции разбросаны с анонимными функциями, используемыми в
lapply
тип функций, например:
aFunc<-function(somedataframe) { result<-lapply(seq_along(somedataframe), function(i){ catw("working on col", i, "/", ncol(somedataframe)) #do some more stuff here and return something return(sum(is.na(somedataframe[[i]]))) } }
- > для этих случаев, по-видимому (и понятно) мне нужно n = 3 в вызове sys.parent
в моей функции catw
.
- Я иногда использую
do.call
: это моя текущая реализация тоже не работает (я еще раз могу это понять, хотя Я не понял это полностью.
Итак, мой вопрос: есть ли способ найти первую именованную функцию выше в callstack (пропустить самую функцию ведения журнала и, возможно, некоторые другие "известные" исключения), что позволило бы мне написать одну единственную версию catw
для всех случаев (так что я могу с радостью реорганизовать, не беспокоясь о моем протоколе ведения журнала)? Как бы вы поступили примерно так?
Изменить: эти случаи должны поддерживаться:
testa<-function(par1)
{
catw("Hello from testa, par1=", par1)
for(i in 1:2) catw("normal loop from testa, item", i)
rv<-sapply(1:2, function(i){catw("sapply from testa, item", i);return(i)})
return(rv)
}
testb<-function(par1, par2)
{
catw("Hello from testb, par1=", par1)
for(i in 1:2) catw("normal loop from testb, item", i)
rv<-sapply(1:2, function(i){catw("sapply from testb, item", i);return(i)})
catw("Will now call testa from testb")
rv2<-testa(par1)
catw("Back from testa call in testb")
catw("Will now do.call testa from testb")
rv2<-do.call(testa, list(par1))
catw("Back from testa do.call in testb")
return(list(rv, rv2))
}
testa(123)
testb(123,456)
do.call(testb, list(123,456))