【发布时间】:2019-12-18 06:26:57
【问题描述】:
我正在尝试向 CRAN 提交一个包。我的函数很长,几千行。我重写了它并将其分解为一个包装器(“外部”)函数,该函数调用一组“内部”子函数(未导出),这些子函数创建了我想要返回到包装器函数环境的对象。我尝试过使用 assign() 函数或 list2env(),它们的作用相同,只是它接受一个列表作为参数并返回在列表中命名为它们的命名元素的对象。当我对我的包运行 R CMD 检查时,会触发“全局变量没有可见绑定”警告,因为在子函数中创建了许多变量并从这些函数中返回到环境中,并在包装器环境中使用之后没有在此环境中创建它们的显式实例。
我之前在网上看到过有关此的问题。其中一些专门处理 ggplot、dplyr 或子集或 data.frame 问题。这个比较笼统。一些在线参考资料提到使用 utils::globalVariables 函数 (https://github.com/r-lib/devtools/issues/1714) 首先将这些变量声明为稍后创建的全局变量。论坛提到要么将它们放在单独的 globals.R 脚本中,要么放在我的包装函数开头的函数调用中。但这种解决方案似乎作为“黑客”而备受争议。另一个解决方案(同样“hackish”,但我想还可以)只是在代码开头将所有这些变量初始化为 NULL。
我看到的另一个解决方案是基本上将所有这些对象存储为在包装函数中初始化的列表的成员,然后返回子函数的所有输出以附加或修改列表项。这样,我要创建的全局对象不是单独的单独对象,而是列表的一部分,所以没有问题。但是,然后我需要特别重写我的代码以将每个对象称为列表项(例如,tmp$obj 而不仅仅是 obj)。另一方面,这在某种程度上更简单,因为所有对象都存储在一个列表中,可以作为一个单元引用和传递,而不必单独跟踪它们。
我想听听有经验的人对这些方法的各种优点/缺点或正确性的看法。
将对象返回到环境
outside_function <- function() {
k <- letters[17:23]
#inside_function creates objects m and z which did not exist before
inside_function()
ls()
print(m)
print(z)
inside_function()
ls()
#z and m should now be overwritten
print(m)
print(z)
}
inside_function <- function() {
m <- matrix(runif(4), ncol=2)
z <- letters[1:10]
#assign to the wrapping environment
assign("m", m, envir=parent.frame())
assign("z", z, envir=parent.frame())
#an equivalent way:
list2env(list(m=m, z=z), envir=parent.frame())
}
另一种方式,将对象保存为列表
outside_function <- function() {
k <- letters[17:23]
#inside_function creates objects m and z which did not exist before
tmp <- inside_function()
#refer to m and z only as items in tmp
print(tmp$m)
print(tmp$z)
tmp <- inside_function()
ls()
#z and m should now be overwritten
print(tmp$m)
print(tmp$z)
}
inside_function <- function() {
m <- matrix(runif(4), ncol=2)
z <- letters[1:10]
#return as list items
list(m=m, z=z)
}
对于第一个,我得到以下注释:
outside_function: no visible binding for global variable 'm'
outside_function: no visible binding for global variable 'z'
【问题讨论】:
-
这是主观的,但我肯定会支持列表方法。对我来说,拥有自包含并返回特定值的函数似乎要干净得多,而不是让它们与“全局状态”混为一谈。 (“全局状态”在这里并不严格,但在大多数语言中都是这样描述的)。
-
查看我上面的编辑。我想出了如何使用环境
-
很高兴听到你想通了。您可以在 Stack Overflow 上回答您自己的问题(我忘记了确切的规则,但我认为您也可以在短时间内“接受”它作为最佳答案),因此请随时将其发布为答案。跨度>
标签: r package environment-variables devtools cran