什么时候值得在 R 函数中使用“remove”?

ms6*_*609 3 performance r function

在决定是否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
}
Run Code Online (Sandbox Code Playgroud)

我知道tmp当函数完成执行时它将被删除,但我是否应该担心提前删除它?

Moo*_*per 5

来自Hadley Wickham 的高级 R

在某些语言中,您必须显式删除未使用的对象才能返回其内存。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'"
Run Code Online (Sandbox Code Playgroud)

由reprex 包(v0.3.0)于 2019-07-08 创建

在这种情况下,如果您想控制封闭环境中可用的变量,或者确保不会混乱您的内存,您可能需要删除不必要的对象,或者像您那样使用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
Run Code Online (Sandbox Code Playgroud)

由reprex 包(v0.3.0)于 2019-07-08 创建