为什么函数内部的rm不能删除对象?

时间:2016-09-02 17:19:17

标签: r

rel.mem <- function(nm) {
  rm(nm)
}

我定义了上面的函数rel.mem - 接受一个参数并将其传递给rm

> ls()
[1] "rel.mem"
> x<-1:10
> ls()
[1] "rel.mem" "x"      
> rel.mem(x)
> ls()
[1] "rel.mem" "x"    

现在你可以看到我所谓的rel.mem x没有被删除 - 我知道这是由于正在尝试使用rm的环境不正确。

对此有什么好的解决方法?

良好解决方案的标准:

  1. 来电者不必通过环境
  2. 被调用者(rel.mem)应该能够通过使用R语言工具(调用栈检查,方面等)来确定环境。
  3. 函数rel.mem的接口应该保持简单 - 白痴证明:调用rel.mem - 然后rel.mem从那里接收它 - 不需要通过环境。
  4. 注意:

    1. 许多评论者指出,一个简单的解决办法是通过环境。
    2. 我的意思是一个好的修复[我应该澄清]是被调用函数(在本例中为rel.mem)能够在调用者引用时计算/找出环境,然后删除来自正确环境的物体。
    3. &#34; 2&#34;中的推理类型可以通过检查调用堆栈来完成其他语言 - 例如在Java中我会抛出一个虚拟异常 - 捕获它然后解析调用堆栈。在其他语言中,我仍然可以使用面向方面的技术。问题是可以在R中完成吗?
    4. 一位评论者建议可能有多个具有相同名称的对象,因此&#34; right&#34;环境毫无意义 - 正如我上面所说,在其他语言中,有可能(有时带有一些创造性的诡计)来解释调用堆栈 - 这在R
    5. 中可能是不可能的。
    6. 正如一位评论者建议rm(list = nm,envir = parent.frame())将从父环境中删除它。这是正确的 - 但是我正在寻找适用于任意调用深度的东西。

2 个答案:

答案 0 :(得分:12)

快速回答是您处于不同的环境中 - 实际上是在框中描绘变量:您有一个功能框和一个全局环境框。您只需要告诉rm在哪里找到该框。

所以

rel_mem <- function(nm) {
   # State the environment
   rm(list=nm, envir = .GlobalEnv )
}
x = 10
rel_mem("x")

或者,您可以使用pos参数,例如

rel_mem <- function(nm) {
   rm(list=nm, pos=1 )
}

如果您输入search(),您会看到一个环境向量,全局数字为1

另外两个选项是

  • envir = parent.frame()如果你想在调用堆栈上升一级
  • 使用inherits = TRUE上调调用堆栈直到找到

在上面的代码中,请注意我将对象作为字符传递 - 我正在传递"x"而不是x。我们可以聪明并使用substitute函数

来避免这种情况
rel_mem <- function(nm) {
   rm(list = as.character(substitute(nm)), envir = .GlobalEnv )
}

要完成,我只想补充一点,从函数中删除.GlobalEnv中的内容通常是糟糕的想法。

更多资源:

答案 1 :(得分:0)

如果您正在使用另一个函数在函数中查找全局对象,例如ls(),则也必须在其中明确声明环境:

rel_mem <- function(nm) {
   # State the environment in both functions
   rm(list = ls(envir = .GlobalEnv) %>% .[startsWith(., "plot_")], envir = .GlobalEnv)
}