R 包中的 .First.lib 习惯用法

发布于 2024-10-06 10:54:17 字数 793 浏览 0 评论 0原文

我在很多 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

耶耶耶 2024-10-13 10:54:17

这种成语很古老。包应该有命名空间并使用 .onLoad、.onUnload 和 .onAttach。例如:

.onLoad <- function(libname, pkgname){
     # do whatever needs to be done when the package is loaded
     # some people use it to bombard users with 
     # messages using 
     packageStartupMessage( "my package is so cool" )
     packageStartupMessage( "so I will print these lines each time you load it")
}

最好通过将以下内容添加到描述文件来避免调用lazyLoad函数的整个事务:

LazyLoad: true

That kind of idiom is antique. Packages should have namespaces and use .onLoad, .onUnload and .onAttach. For example:

.onLoad <- function(libname, pkgname){
     # do whatever needs to be done when the package is loaded
     # some people use it to bombard users with 
     # messages using 
     packageStartupMessage( "my package is so cool" )
     packageStartupMessage( "so I will print these lines each time you load it")
}

The whold business with the calling the lazyLoad function is best avoided by just adding this to the DESCRIPTION file:

LazyLoad: true
平安喜乐 2024-10-13 10:54:17

您问为什么脚本之前删除了 .First.Lib 时它还要查找它。 lazyLoad 加载 R 对象的数据库,在上面的代码中该数据库被加载到环境 myEnv 中。加载到该环境中的对象集包含 .First.Lib 并不是不可想象的,而代码正在寻找它。事实上,我猜其目的是运行存储在加载的对象数据库中的.First.Lib

没有命名空间的包中的另一个常见习惯用法是这样的(来自 vegan 包):

.First.lib <- function(lib, pkg)  {
    library.dynam("vegan", pkg, lib)
    packageStartupMessage("This is vegan ",
                          utils::packageDescription("vegan", field="Version"),
                          appendLF = TRUE)
}

这会加载可供使用的已编译代码,并打印一条带有包名称和版本号的简单启动消息。这在本质上与 @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 environment myEnv. 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):

.First.lib <- function(lib, pkg)  {
    library.dynam("vegan", pkg, lib)
    packageStartupMessage("This is vegan ",
                          utils::packageDescription("vegan", field="Version"),
                          appendLF = TRUE)
}

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文