偶爾需要修補程序包中的函數,而無需重新編譯整個程序包。R:修補程序包功能並重新加載基礎庫
例如,在Emacs ESS中,如果未加載tcltk
,函數install.packages()
可能會卡住。有人可能想要在安裝之前補丁install.packages()
以便要求tcltk
,並且在安裝軟件包之後卸載它。
的install.packages()
一個temp()
修補版本可能是:
## Get original args without ending NULL
temp=rev(rev(deparse(args(install.packages)))[-1])
temp=paste(paste(temp, collapse="\n"),
## Add code to load tcltk
"{",
" wasloaded= 'package:tcltk' %in% search()",
" require(tcltk)",
## Add orginal body without braces
paste(rev(rev(deparse(body(install.packages))[-1])[-1]), collapse="\n"),
## Unload tcltk if it was not loaded before by user
" if(!wasloaded) detach('package:tcltk', unload=TRUE)",
"}\n",
sep="\n")
## Eval patched function
temp=eval(parse(text=temp))
# temp
現在,我們要取代原來的install.packages()
或許插入代碼Rprofile
。
爲此,它是沒有價值的是:
getAnywhere("install.packages")
# A single object matching 'install.packages' was found
# It was found in the following places
# package:utils
# namespace:utils
# with value
#
# ... install.packages() source follows (quite lengthy)
也就是說,函數存儲的utils
包/命名空間內。這個環境是密封的,因此install.packages()
應該被解鎖被替換之前:
## Override original function
unlockBinding("install.packages", as.environment("package:utils"))
assign("install.packages", temp, envir=as.environment("package:utils"))
unlockBinding("install.packages", asNamespace("utils"))
assign("install.packages", temp, envir=asNamespace("utils"))
rm(temp)
使用getAnywhere()
再次,我們得到:
getAnywhere("install.packages")
# A single object matching 'install.packages' was found
# It was found in the following places
# package:utils
# namespace:utils
# with value
#
# ... the *new* install.packages() source follows
看來,打補丁函數被放置在正確的地方。
不幸的是,運行它給:
Error in install.packages(xxxxx) :
could not find function "getDependencies"
getDependencies()
相同utils
封裝內的功能,但不出口;因此它不能在其名稱空間外訪問。
儘管輸出爲getAnywhere("install.packages")
,但修補的install.packages()
仍然錯位。
問題是我們需要重新加載utils
庫以獲得所需的效果,這也需要卸載導入它的其他庫。
detach("package:stats", unload=TRUE)
detach("package:graphics", unload=TRUE)
detach("package:grDevices", unload=TRUE)
detach("package:utils", unload=TRUE)
library(utils)
install.packages()
現在起作用。
當然,我們也需要重新加載其他庫。鑑於依賴關係,使用
library(stats)
應重新載入所有內容。
library(graphics)
# Error in FUN(X[[i]], ...) :
# no such symbol C_contour in package path/to/library/graphics/libs/x64/graphics.dll
這是(重新)的正確方法加載graphics
庫:但重裝時graphics
庫,至少在Windows上是一個問題嗎?
在描述示例的目的時,你失去了我,但當我看到eval(parse())時,我停止閱讀。 – Roland