Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is there a way to list all environments (environment names) in R

Tags:

r

environment

I am studying "environment" concept in R. Now I know emptyenv() is the parent of all environments and it has no parent, but is there a way to list all environments in current R session or say children of emptyenv()?

like image 760
AAA Avatar asked Dec 26 '19 16:12

AAA


2 Answers

My solution is looking for environments recursively. We could do it because of the fact that additional/new environments have to be create in a visible/known place. Still, there might be some lesser edge cases like environments inside functions or R6 classes:

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

Another thing will be to grab e.g. environment of the function body, inside {}. It will be created during function evaluation not creation. This might be almost impossible.

I am demanding that the object recognized as an environment - is.environment and inherits(e, "environment"). The latter condition protecting us against objects like ggproto loaded with 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()

results:

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

[[2]]
<environment: 0x7f9c75e65600>

[[3]]
<environment: 0x7f9c75e68e80>

[[4]]
<environment: 0x7f9c75e65e88>

[[5]]
<environment: 0x7f9c75e67ec0>

[[6]]
<environment: 0x7f9c75e6df38>

[[7]]
<environment: 0x7f9c75e6ef30>

EDIT:

This function might be used to maximize environments visibility.

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

Unfortunately when some package is built it will be using base::new.env by default. Even assignInNamespace might not be satisfactory here.

like image 173
polkas Avatar answered Sep 25 '22 20:09

polkas


Rather than look at all of the children of the empty environment, we can look at the parents of the global environment. This is an imperfect solution because some environments can exist is ways that are not parents of the global environment, but it's at least a partial solution.

The following recursive function will return a list of all environments exist as parents (grandparents, etc.) of the env argument. If you don't specify an environment, the global environment is used.

allParents = function(env = globalenv(), result = list()) {
  result = c(list(parent.env(env)), result)
  if(!identical(result[[1]], emptyenv())) {
    result <- allParents(result[[1]], result)
  }
  return(result)
}

allParents()

yields, for instance:

[[1]]
<environment: R_EmptyEnv>

[[2]]
<environment: base>

[[3]]
<environment: 0x55b78fe34790>
attr(,"name")
[1] "org:r-lib"

[[4]]
<environment: 0x55b78bc4dfe8>
attr(,"name")
[1] "Autoloads"

[[5]]
<environment: package:methods>
attr(,"name")
[1] "package:methods"
attr(,"path")
[1] "/usr/lib/R/library/methods"

[[6]]
<environment: package:datasets>
attr(,"name")
[1] "package:datasets"
attr(,"path")
[1] "/usr/lib/R/library/datasets"

[[7]]
<environment: package:utils>
attr(,"name")
[1] "package:utils"
attr(,"path")
[1] "/usr/lib/R/library/utils"

[[8]]
<environment: package:grDevices>
attr(,"name")
[1] "package:grDevices"
attr(,"path")
[1] "/usr/lib/R/library/grDevices"

[[9]]
<environment: package:graphics>
attr(,"name")
[1] "package:graphics"
attr(,"path")
[1] "/usr/lib/R/library/graphics"

[[10]]
<environment: package:stats>
attr(,"name")
[1] "package:stats"
attr(,"path")
[1] "/usr/lib/R/library/stats"

[[11]]
<environment: 0x55b78d81bd78>
attr(,"name")
[1] "tools:rstudio"
like image 20
Geoffrey Poole Avatar answered Sep 26 '22 20:09

Geoffrey Poole