r - 什么时候值得在 R 函数中使用`remove`?
问题描述
在决定是否remove
将不会在函数中再次使用的变量时,我应该考虑哪些因素?
这是一个点头的例子:
DivideByLower <- function (a, b) {
if (a > b) {
tmp <- a
a <- b
b <- tmp
remove(tmp) # When should I include this line?
}
# Return:
a / b
}
我知道tmp
当函数完成执行时它将被删除,但我是否应该担心提前删除它?
解决方案
在某些语言中,您必须显式删除未使用的对象才能返回它们的内存。R 使用了另一种方法:垃圾收集(或简称 GC)。当不再使用对象时,GC 会自动释放内存。它通过跟踪有多少名称指向每个对象来做到这一点,并且当没有名称指向一个对象时,它会删除该对象。
在您描述垃圾收集的情况下,将释放内存。
如果您的函数的输出是另一个函数,在这种情况下,Hadley 将这些函数分别命名为函数工厂和制造函数,在函数工厂主体中创建的变量将在制造函数的封闭环境中可用,并且内存不会被释放。
更多信息,仍然在 Hadley 的书中,可以在关于函数工厂的章节中找到。
function_factory <- function(x){
force(x)
y <- "bar"
fun <- function(z){
sprintf("x, y, and z are all accessible and their values are '%s', '%s', and '%s'",
x, y, z)
}
fun
}
manufactured_function <- function_factory("foo")
manufactured_function("baz")
#> [1] "x, y, and z are all accessible and their values are 'foo', 'bar', and 'baz'"
由reprex 包(v0.3.0)于 2019 年 7 月 8 日创建
在这种情况下,如果您想控制封闭环境中可用的变量,或者确保您不会弄乱您的记忆,您可能希望删除不必要的对象,或者像您所做的那样使用rm
/ remove
,或者像我倾向于喜欢,包裹在一个on.exit
声明中。
我可能会使用 rm 的另一种情况是,如果我想从父环境访问变量而不会有在函数内部被覆盖的风险,但在这种情况下,通常可以使用eval.parent
.
y <- 2
z <- 3
test0 <- function(x, var){
y <- 1
x + eval(substitute(var))
}
# opps, the value of y is the one defined in the body
test0(0, y)
#> [1] 1
test0(0, z)
#> [1] 3
# but it will work using eval.parent :
test1 <- function(x, var){
y <- 1
x + eval.parent(substitute(var))
}
test1(0, y)
#> [1] 2
test1(0, z)
#> [1] 3
# in some cases (better avoided), it can be easier/quick and dirty to do something like :
test2 <- function(x, var){
y <- 1
# whatever code using y
rm(y)
x + eval(substitute(var))
}
test2(0, y)
#> [1] 2
test2(0, z)
#> [1] 3
由reprex 包(v0.3.0)于 2019 年 7 月 8 日创建
推荐阅读
- c - 代码库的哪些部分使二进制文件变大了?
- javascript - 请求对应日期范围的mongodb对象
- python - 根据特定元素打印列表中的元素
- javascript - 无效的回发或回调参数。当点击提交按钮
- reactjs - 如何同步更新反应状态
- clojure - 如何在clojure中为变量重新分配另一个值
- php - 生成/下载大型 Excel 文件 - PhpExcel
- c# - 如何在 C# 中应用 MongoDb 集合之间的连接
- javascript - AngularJS - $http 加载资源失败:服务器响应状态为 404
- liferay - 如何从 liferay portlet 工具栏中删除“更多”按钮