【问题标题】:Why does rm inside a function not delete objects?为什么函数内部的 rm 不删除对象?
【发布时间】:2016-09-02 17:19:17
【问题描述】:
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 从那里获取它——无需传递环境。

注意事项:

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

【问题讨论】:

  • 另外,请不要在您的问题中发布诸如rm(list = ls()) 之类的命令,除非它们对理解您的问题至关重要 - 您不希望任何人意外运行它们.
  • @Gregor -- 实际上我应该指定 -- 我的问题是 -- 有没有办法在不每次都明确传递环境的情况下做到这一点?
  • @Gregor -- 请查看更新后的问题...谢谢。
  • 问题指定不充分。在不同的环境中可以有多个具有相同名称的对象。 “正确的环境”是如何定义的?
  • @ZheyuanLi:如果提问者希望“正确答案”是删除找到当前搜索路径的命名对象的第一个实例(在调用函数时),那么我认为使用apropos() 来确定移除的“目标”可能会成功。

标签: r


【解决方案1】:

快速回答是您处于不同的环境中 - 本质上是在一个盒子中描绘变量:您有一个用于函数的盒子和一个用于全局环境的盒子。你只需要告诉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 中的内容通常是一个的想法。

更多资源:

【讨论】:

  • 非常感谢您的回答——我已经更新了问题——如果有任何意见,我将不胜感激。谢谢。
  • @BenBolker 你是对的——我正在寻找一个任意的祖先定位器机制
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 2017-06-06
    • 2018-04-08
    • 1970-01-01
    • 1970-01-01
    • 2017-03-27
    • 2017-05-18
    • 1970-01-01
    • 2019-01-29
    • 2017-12-16
    相关资源
    最近更新 更多