我有幾個自定義日誌函數,它們是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。*」)。 –