R如何在加载时使变量可用于命名空间

时间:2018-03-01 18:46:13

标签: r devtools r-package

在我的一个软件包中,我使用.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钩子中进行分配的正确性是什么?

2 个答案:

答案 0 :(得分:11)

按照this answer中针对相关问题的方法,您可以更改.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

  

有四种特殊环境:

     

...

     
      
  • environment()是当前环境。
  •   
     

...

     

您可以使用ls()和列出环境框架中的绑定   通过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>

在会话开始时打印到控制台。这样,您就可以在环境variable中分配namespace:MyRPackage,即使尝试assign("variable", variable, envir = namespace:MyRPackage)会导致错误

  

错误:“MyRPackage”的包或名称空间加载失败:

     对于'MyRPackage',

.onLoad在loadNamespace()中失败,详情:

     

call:get(name,envir = ns,inherits = FALSE)

     

错误:未找到对象“命名空间”

安装包时。

答案 1 :(得分:0)

基本上有两种方式:

  1. 通过assignInMyNamespace(…)
  2. 通过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())
}