R 包中的 .First.lib 习惯用法
我在很多 R 包的 .First.lib 函数中看到以下习惯用法:
fullName <- paste("package", pkgname, sep=":")
myEnv <- as.environment(match(fullName, search()))
barepackage <- sub("([^-]+)_.*", "\\1", pkgname)
dbbase <- file.path(libname, pkgname, "R", barepackage)
rm(.First.lib, envir = myEnv)
lazyLoad(dbbase, myEnv)
if(exists(".First.lib", envir = myEnv, inherits = FALSE)) {
f <- get(".First.lib", envir = myEnv, inherits = FALSE)
if(is.function(f))
f(libname, pkgname)
else
stop(gettextf("package '%s' has a non-function '.First.lib'",
pkgname),
domain = NA)
}
我知道 .First.lib 函数在加载包时运行。
我知道上面的代码定义了包的环境并设置了路径,但我不明白为什么它在显式删除 .First.lib 函数后还要寻找 .First.lib 函数。是什么让上述习语如此普遍?将其包含在 R 包中是“最佳实践”吗?
I see the following idiom in the .First.lib function in a lot of R packages:
fullName <- paste("package", pkgname, sep=":")
myEnv <- as.environment(match(fullName, search()))
barepackage <- sub("([^-]+)_.*", "\\1", pkgname)
dbbase <- file.path(libname, pkgname, "R", barepackage)
rm(.First.lib, envir = myEnv)
lazyLoad(dbbase, myEnv)
if(exists(".First.lib", envir = myEnv, inherits = FALSE)) {
f <- get(".First.lib", envir = myEnv, inherits = FALSE)
if(is.function(f))
f(libname, pkgname)
else
stop(gettextf("package '%s' has a non-function '.First.lib'",
pkgname),
domain = NA)
}
I understand that the .First.lib function is run when a package is loaded.
I understand that the code above defines an environment for the package and sets up a path, but I don't understand why it's looking for a .First.lib function after it explicitly deletes the .First.lib function. What makes the above idiom so common? Is it a "best practice" to include this in an R package?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这种成语很古老。包应该有命名空间并使用 .onLoad、.onUnload 和 .onAttach。例如:
最好通过将以下内容添加到描述文件来避免调用lazyLoad函数的整个事务:
That kind of idiom is antique. Packages should have namespaces and use .onLoad, .onUnload and .onAttach. For example:
The whold business with the calling the lazyLoad function is best avoided by just adding this to the DESCRIPTION file:
您问为什么脚本之前删除了
.First.Lib
时它还要查找它。lazyLoad
加载 R 对象的数据库,在上面的代码中该数据库被加载到环境myEnv
中。加载到该环境中的对象集包含.First.Lib
并不是不可想象的,而代码正在寻找它。事实上,我猜其目的是仅运行存储在加载的对象数据库中的.First.Lib
。没有命名空间的包中的另一个常见习惯用法是这样的(来自 vegan 包):
这会加载可供使用的已编译代码,并打印一条带有包名称和版本号的简单启动消息。这在本质上与 @Romain 的答案的
.onLoad
类似,但没有 NAMESPACE。You ask why it is looking for
.First.Lib
when the script deleted it earlier.lazyLoad
loads a database of R objects, which in the code above is loaded into the environmentmyEnv
. It is not inconceivable that the set of objects loaded into that environment contains a.First.Lib
and it is this that the code is looking for. Indeed, I guess the intention was to only run the.First.Lib
that was stored in the object database loaded.Another common idiom in packages without a NAMESPACE, is this (from the vegan package):
This loads the compiled code ready for use and prints a simple start-up message with the package name and version number. This is similar in spirit to the
.onLoad
of @Romain's answer, but without the NAMESPACE.