我有第一个包,其中使用下载并动态存储在缓存中的数据集 通过 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)
这个机制有效。
审稿人的主要评论是:
- 如果您使用环境变量(甚至选项),那么 应该不需要使用
。只调用Sys.getenv。用户 将在其系统上设置环境变量的值。assign
- 如果定义了所有变量,则不需要使用
在函数环境中,在这种情况下,您只需调用 按名称指定对象。get
我不知道如何在不使用
assign
或 Sys.getenv 的情况下纠正这个问题并遵循良好
发展实践。
更新:我写了Sys.getenv,而它应该是
get
。对不起。
代码中真正的问题是使用
attach()
。 attach()
修改全局状态(特别是通过搜索路径),这在包中是不允许的(有一些明确定义的例外)——无论是在 CRAN 上还是在 Bioconductor 上。
幸运的是,无论如何,这对于您的目的来说似乎完全没有必要。这是你可以/应该做的:
A
)。as.environment()
这是一个粗略的轮廓:
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()
。