【问题标题】:is there a way to list all environments (environment names) in R有没有办法在 R 中列出所有环境(环境名称)
【发布时间】:2019-12-26 16:51:10
【问题描述】:

我正在研究 R 中的“环境”概念。 现在我知道emptyenv() 是所有环境的父级并且它没有父级,但是有没有办法列出当前 R 会话中的所有环境或者说emptyenv() 的子级?

【问题讨论】:

  • 虽然parent.env(e)会返回一个环境的父环境,但我认为没有反向功能。
  • @r2evans 这是一个旧的。我认为我们不需要parent.env 的反向函数。看看我的回答。谢谢

标签: r environment


【解决方案1】:

我的解决方案是递归地寻找环境。我们可以这样做,因为必须在可见/已知的地方创建附加/新环境。不过,可能还有一些较小的边缘情况,例如函数或 R6 类中的环境:

fun <- function() {
  ee <- new.env()
  fun2 <-  function() {
    eee <- new.env()
  }
  return(1)
}

另一件事是抓住例如函数体的环境,在 {} 内。它将在函数评估而不是创建期间创建。这几乎是不可能的。

我要求将对象识别为环境 - is.environmentinherits(e, "environment")。后一种条件可以保护我们免受像 ggproto 这样的带有 ggplot2 的对象的攻击。

set.seed(1234)

# New environments - x7
#######################
eval(quote(ee <- new.env(parent = baseenv())))

eval(quote(ee1 <- new.env(parent = baseenv())), envir = ee)

ee2 <- new.env()

ee3 <- new.env(parent = ee2)

eval(quote(ee4 <- new.env(parent = baseenv())), envir = ee3)

eval(quote(ee5 <- new.env()), envir = baseenv())

eval(quote(ee6 <- new.env(parent = .GlobalEnv)), envir = ee3)


#######################

subenv <- function(env) {
  envs <- unique(Filter(function(e) is.environment(e) && inherits(e, "environment"), lapply(ls(env), function(x) get(x, env))))
  unlist(append(envs, lapply(envs, subenv)))
}

search_all = function() {
  ees <- unlist(append(.GlobalEnv, rlang::env_parents(.GlobalEnv)))
  unname(unlist(lapply(ees, subenv)))
}

library(ggplot2) 

search_all()

结果:

> search_all()
[[1]]
<environment: 0x7f9c75e66e10>

[[2]]
<environment: 0x7f9c75e65600>

[[3]]
<environment: 0x7f9c75e68e80>

[[4]]
<environment: 0x7f9c75e65e88>

[[5]]
<environment: 0x7f9c75e67ec0>

[[6]]
<environment: 0x7f9c75e6df38>

[[7]]
<environment: 0x7f9c75e6ef30>

编辑:

此功能可用于最大化环境可见性。

new.env <- function(...) {
  ee <- base::new.env(...)
  if(!identical(parent.frame(), .GlobalEnv)) {
    assign(paste0("env_", data.table::address(ee)), ee, envir = .GlobalEnv)
    }
  ee
}

不幸的是,当构建某些包时,它将默认使用 base::new.env。即便是assignInNamespace 在这里也可能不尽如人意。

【讨论】:

    【解决方案2】:

    这样做的唯一方法是列出会话中的所有对象,以及环境对象的子集,而这在 R 代码中是不可能的。

    您可以通过递归搜索全局环境中的所有内容以及其中的对象所引用的环境(例如,每个函数和公式都引用一个环境)来列出大多数对象,并继续其父环境等. 然而,这不会得到一切,因为包可以从它们的 C 代码中创建对象,而这些对象不能直接从 R 代码访问。

    如果您愿意编写棘手的低级 C 代码,则必须在 R 的堆中进行与垃圾收集器相同的搜索。堆包含每个对象,但在垃圾收集发生之前并不能真正区分已删除或未删除的对象。因此,您可能会发现一些无法真正访问的环境。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-25
      • 1970-01-01
      • 2011-11-04
      • 1970-01-01
      • 2012-06-25
      • 2020-10-29
      相关资源
      最近更新 更多