在 Bioconductor 包中正确使用嵌套环境

问题描述 投票:0回答:1

我有第一个包,其中使用下载并动态存储在缓存中的数据集 通过 BiocFileCache 它被用作参考,在我的代码中到处调用,但用户也可以修改它。

基于第一个包开发的第二个包也将使用此参考。

我发现使用嵌套环境来解决这个问题是一种方便的解决方案,但它没有通过 Bioconductor 的良好实践。我使用在加载的所有包顶部的空环境下声明的环境。

第一个包在

zzz.R
文件中声明此环境变量:

.onLoad <- function(...) {

    nameEnv <- "My-Env"
    myEnv <- new.env(parent = emptyenv()) 
    attach(myEnv, name = nameEnv)
    assign("nameEnv", nameEnv, envir = as.environment(nameEnv))

    assign("Var-1", "/some/dir/here" , envir = as.environment(nameEnv))
}

在代码的其他部分(文件)中,我有时使用以下内容来检索此变量的内容:

Var1 <- get("Var-1")

我可以决定重写其内容:

assign("Var-1", 
        "/some/dir/elsehwhere", envir = as.environment(nameEnv)

这个机制有效。

审稿人的主要评论是:

  1. 如果您使用环境变量(甚至选项),那么 应该不需要使用
    assign
    。只调用Sys.getenv。用户 将在其系统上设置环境变量的值。
  2. 如果定义了所有变量,则不需要使用
    get
    在函数环境中,在这种情况下,您只需调用 按名称指定对象。

我不知道如何在不使用

assign
或 Sys.getenv 的情况下纠正这个问题并遵循良好 发展实践。

更新:我写了Sys.getenv,而它应该是

get
。对不起。

r environment r-package bioconductor
1个回答
4
投票

代码中真正的问题是使用

attach()
attach()
修改全局状态(特别是通过搜索路径),这在包中是不允许的(有一些明确定义的例外)——无论是在 CRAN 上还是在 Bioconductor 上。

幸运的是,无论如何,这对于您的目的来说似乎完全没有必要。这是你可以/应该做的:

  1. 在包的命名空间内创建环境(我们称此包为
    A
    )。
  2. 通过变量名称而不是通过
    as.environment()
  3. 引用该环境
  4. 创建用于在该环境中读取和写入值的函数,并导出这些函数,以便可以从其他包中使用它们。

这是一个粗略的轮廓:

store = new.env(parent = emptyenv())

.onLoad = function (lib, pkg) {
  store$var1 = "/some/dir/here"
}

#' @export
read = function (name) {
  get(name, envir = store)
}

#' @export
write = function (name, value) {
  assign(name, value, envir = store)
}

现在您可以使用

A::read("var1")

您还可以导出

store
环境本身,以允许用户编写
A::store$var1
;然而,R 的语法禁止通过
mystore::store$var1 = "new value"
直接赋值(这可以说是(…)R 解释器中的一个错误,但修复它被认为很复杂,用处太小)。因此,对于分配,您需要创建一个临时别名:

store = A::store
store$var1 = "new value"

…或诉诸使用

assign()

© www.soinside.com 2019 - 2024. All rights reserved.