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

use*_*468 5 r

rel.mem <- function(nm) {
  rm(nm)
}
Run Code Online (Sandbox Code Playgroud)

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

> ls()
[1] "rel.mem"
> x<-1:10
> ls()
[1] "rel.mem" "x"      
> rel.mem(x)
> ls()
[1] "rel.mem" "x"    
Run Code Online (Sandbox Code Playgroud)

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

对此有什么好处?

一个好的修复的标准:

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

笔记:

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

csg*_*pie 12

快速回答是您处于不同的环境中 - 实际上是在框中描绘变量:您有一个功能框和一个全局环境框.你只需要知道rm在哪里找到那个盒子.

所以

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

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

rel_mem <- function(nm) {
   rm(list=nm, pos=1 )
}
Run Code Online (Sandbox Code Playgroud)

如果键入,search()您将看到环境向量,全局为数字1.

另外两个选择是

  • envir = parent.frame() 如果你想在调用堆栈上升一级
  • 用于inherits = TRUE上调调用堆栈,直到找到某些内容

在上面的代码中,请注意我将对象作为一个字符传递 - 我正在传递"x"not x.我们可以聪明并使用该substitute功能避免这种情况

rel_mem <- function(nm) {
   rm(list = as.character(substitute(nm)), envir = .GlobalEnv )
}
Run Code Online (Sandbox Code Playgroud)

要完成,我只想补充说,.GlobalEnv从函数中删除东西通常是个主意.

更多资源: