如何在加载时使变量对命名空间可用
How to make variable available to namespace at loading time
在我的一个包中,我使用 .onAttach
挂钩 运行 一些 R 代码,然后使用 assign
使该值可用作包变量之一。我这样做是因为 variable
取决于某个文件的内容,它可以在一个会话和另一个会话之间发生变化。我使用的代码是这样的:
.onAttach <- function(libname, pkgname) {
variable <- some_function()
assign("variable", variable, envir = as.environment("package:MyRPackage"))
}
当我用 library(MyRpackage)
附加包裹时,我可以使用 variable
。
但是不可能做类似MyRPackage::variable
的事情(除非我已经用library(MyRpackage)
附加了包裹。
我知道这是因为我应该将该代码放在 .onLoad
挂钩中,但是我无法进行分配以使其正常工作。
我试过了
.onLoad <- function(libname, pkgname) {
variable <- some_function()
assign("variable", variable, envir = as.environment("namesoace:MyRPackage"))
}
和
.onLoad <- function(libname, pkgname) {
variable <- some_function()
assign("variable", variable, envir = asNamespace("MyRPackage"))
}
但是当我 运行 MyRPackage:::variable
没有使用 library
附加包时,它们都失败并出现一些错误。
.onLoad hook 中的正确赋值是什么?
按照 中的方法解决相关问题,您可以像这样更改 .onLoad()
函数:
.onLoad <- function(libname, pkgname) {
variable <- some_function()
assign("variable", variable, envir = parent.env(environment()))
}
然后您可以访问 variable
而无需使用 MyRPackage:::variable
附加包。我不知道你用 some_function()
做了什么,所以我用一个虚拟包尝试了以下操作:
.onLoad <- function(libname, pkgname) {
variable <- 42
assign("variable", variable, envir = parent.env(environment()))
}
在新的 R 会话中,结果是
> MyRPackage:::variable
[1] 42
进一步说明
来自 Hadley Wickham 的 Advanced R:
There are four special environments:
...
- The environment() is the current environment.
...
You can list the bindings in the environment’s frame with ls() and
see its parent with parent.env().
因此,如果我们进一步修改 .onLoad()
函数,我们可以看到实际效果:
.onLoad <- function(libname, pkgname) {
print(environment()) # For demonstration purposes only;
print(parent.env(environment())) # Don't really do this.
variable <- 42
assign("variable", variable, envir = parent.env(environment()))
}
然后启动 R 会话会导致
<environment: 0x483da88>
<environment: namespace:MyRPackage>
在会话开始时打印到控制台。这允许您在环境 namespace:MyRPackage
中分配 variable
,即使尝试 assign("variable", variable, envir = namespace:MyRPackage)
会导致错误
Error: package or namespace load failed for ‘MyRPackage’:
.onLoad failed in loadNamespace() for 'MyRPackage', details:
call: get(name, envir = ns, inherits = FALSE)
error: object 'namespace' not found
安装包时。
基本上有两种方式:
- 通过
assignInMyNamespace(…)
- 通过
assign(…, envir = topenv())
虽然选项 1 看起来是 quite widespread,但它实际上需要更多代码,因为您首先需要创建一个变量,然后才能通过 assignInMyNamespace
:
覆盖它
myvar = NULL
.onLoad = function (libname, pkgname) {
assignInMyNamespace('myvar', value)
}
未能预先声明变量将导致错误。
相比之下,assign
完全有能力创建一个以前没有声明过的新变量。我们只需告诉 R 将变量分配到哪个环境中,函数 topenv()
提供了这一点。
.onLoad = function (libname, pkgname) {
assign('myvar', value, envir = topenv())
}
在我的一个包中,我使用 .onAttach
挂钩 运行 一些 R 代码,然后使用 assign
使该值可用作包变量之一。我这样做是因为 variable
取决于某个文件的内容,它可以在一个会话和另一个会话之间发生变化。我使用的代码是这样的:
.onAttach <- function(libname, pkgname) {
variable <- some_function()
assign("variable", variable, envir = as.environment("package:MyRPackage"))
}
当我用 library(MyRpackage)
附加包裹时,我可以使用 variable
。
但是不可能做类似MyRPackage::variable
的事情(除非我已经用library(MyRpackage)
附加了包裹。
我知道这是因为我应该将该代码放在 .onLoad
挂钩中,但是我无法进行分配以使其正常工作。
我试过了
.onLoad <- function(libname, pkgname) {
variable <- some_function()
assign("variable", variable, envir = as.environment("namesoace:MyRPackage"))
}
和
.onLoad <- function(libname, pkgname) {
variable <- some_function()
assign("variable", variable, envir = asNamespace("MyRPackage"))
}
但是当我 运行 MyRPackage:::variable
没有使用 library
附加包时,它们都失败并出现一些错误。
.onLoad hook 中的正确赋值是什么?
按照 .onLoad()
函数:
.onLoad <- function(libname, pkgname) {
variable <- some_function()
assign("variable", variable, envir = parent.env(environment()))
}
然后您可以访问 variable
而无需使用 MyRPackage:::variable
附加包。我不知道你用 some_function()
做了什么,所以我用一个虚拟包尝试了以下操作:
.onLoad <- function(libname, pkgname) {
variable <- 42
assign("variable", variable, envir = parent.env(environment()))
}
在新的 R 会话中,结果是
> MyRPackage:::variable
[1] 42
进一步说明
来自 Hadley Wickham 的 Advanced R:
There are four special environments:
...
- The environment() is the current environment.
...
You can list the bindings in the environment’s frame with ls() and see its parent with parent.env().
因此,如果我们进一步修改 .onLoad()
函数,我们可以看到实际效果:
.onLoad <- function(libname, pkgname) {
print(environment()) # For demonstration purposes only;
print(parent.env(environment())) # Don't really do this.
variable <- 42
assign("variable", variable, envir = parent.env(environment()))
}
然后启动 R 会话会导致
<environment: 0x483da88>
<environment: namespace:MyRPackage>
在会话开始时打印到控制台。这允许您在环境 namespace:MyRPackage
中分配 variable
,即使尝试 assign("variable", variable, envir = namespace:MyRPackage)
会导致错误
Error: package or namespace load failed for ‘MyRPackage’:
.onLoad failed in loadNamespace() for 'MyRPackage', details:
call: get(name, envir = ns, inherits = FALSE)
error: object 'namespace' not found
安装包时。
基本上有两种方式:
- 通过
assignInMyNamespace(…)
- 通过
assign(…, envir = topenv())
虽然选项 1 看起来是 quite widespread,但它实际上需要更多代码,因为您首先需要创建一个变量,然后才能通过 assignInMyNamespace
:
myvar = NULL
.onLoad = function (libname, pkgname) {
assignInMyNamespace('myvar', value)
}
未能预先声明变量将导致错误。
相比之下,assign
完全有能力创建一个以前没有声明过的新变量。我们只需告诉 R 将变量分配到哪个环境中,函数 topenv()
提供了这一点。
.onLoad = function (libname, pkgname) {
assign('myvar', value, envir = topenv())
}