我有几个自定义日志函数,它们是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
每次调用如何与它从调用的函数的名称开头。非常整洁,直到我开始重构我的代码和重命名函数等。
感谢来自Brian Ripley的一些旧的R-list帖子,如果我没有弄错,我发现这个代码得到'当前函数名':
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在我catw
函数的调用sys.parent
。
- 我偶尔使用
do.call
:它出现在我的当前实现 无法正常工作或(我再一次能有所了解的,虽然 我还没有完全想通了
所以,我的问题是:有没有办法找到第一个命名为函数在调用堆栈中更高(跳过日志功能本身,也可能是一些其他“众所周知的”例外),这将允许我为所有人编写一个单一版本的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))
我经常在我的函数中使用'message()'向控制台输出一个音符,告诉我R在函数中的位置。也许,message()和sink(...,type =“message”)的一些实现可以为你工作吗?缺点是你必须把它放在你所有的功能中。 –
假设你为你的函数使用了一个唯一的命名方案,grep是否可以应用于sys.call工作?选择第一个匹配应该是集合中最低的。 – Iterator
@Iterator:函数的命名方案现在不是一个选项。但我愿意与之相反:排除某些方案(如“。* apply。*”)。 –