Find the environment where an object exists

find_object(
  value = NULL,
  name = NULL,
  mode = "any",
  from = parent.frame(),
  until = emptyenv(),
  which = c("first", "last", "all")
)

Arguments

value

The R object whose location should be identified.

name

The name of the object to locate.

mode

The mode of the object to locate.

from

An environment, or an object with an environment (e.g. a function and a formula), to start search from.

until

An environment to consider the last parent environment. If until is not one of the parent environments, then emptyenv() is the last one. It is also possible to specify a list of alternative environments.

which

If "first" or "last", then the first or the last occurrence of object among the parent frames is identified and returned. If "all", then all occurrences are returned.

Value

A named list with elements name and envir, where name is the name of the located object in environment envir. If no object could be located, then NULL is returned. If more than one matching object could be located, then a list of all matching (name, environment) lists is returned if which = "all". If which = "first", then the first match is returned, and if which = "last", then the last match is returned.

Environments searched

A matching object is looked for in environment from. If it is found there, then from is returned. If not found there, the parent environment of from is searched, and so on, until an environment in until, or the "empty" environment (emptyenv()) is reached. In such cases, no matching object could be found and NULL is returned.

Find an object by its value

find_object() with arguments value locates an object of any name with value value in one of the environments searched.

Find an object by its name and mode

find_object() with arguments name and mode locates an object with name name and mode mode in one of the environments searched. This is how base::exists(), base::get(), and base::assign() locate an object based on its name and mode. For example, exists(name) == !is.null(find_object(name = name)).

envir <- find_object(name = name)
if (is.null(envir)) stop(sprintf("Object %s not found", sQuote(name)))
object <- get(name, envir = envir, inherits = FALSE)

Examples

find_object(name = "pi")
#> $name
#> [1] "pi"
#> 
#> $envir
#> <environment: base>
#> 
find_object(name = "pi", mode = "character")   ## non-existing
#> NULL
find_object(name = "rnorm", mode = "function")
#> $name
#> [1] "rnorm"
#> 
#> $envir
#> <environment: package:stats>
#> attr(,"name")
#> [1] "package:stats"
#> attr(,"path")
#> [1] "/home/hb/shared/software/CBI/R-4.2.1-gcc9/lib/R/library/stats"
#> 

f <- local({
  a <- 42
  pi <- 3.14
  function() pi * a
})
env <- find_object(name = "a", from = f)$envir
utils::ls.str(env)
#> a :  num 42
#> pi :  num 3.14

f <- local({
  a <- 42
  local({
    pi <- 3.14
    function() pi * a
  })
})
env_a <- find_object(name = "a", from = f)$envir
utils::ls.str(env_a)
#> a :  num 42
env_pi <- find_object(name = "pi", from = f)$envir
utils::ls.str(env_pi)
#> pi :  num 3.14
stopifnot(
  identical(environment(f), env_pi),
  identical(parent.env(env_pi), env_a)
)

find_object(value = rnorm)
#> $name
#> [1] "rnorm"
#> 
#> $envir
#> <environment: package:stats>
#> attr(,"name")
#> [1] "package:stats"
#> attr(,"path")
#> [1] "/home/hb/shared/software/CBI/R-4.2.1-gcc9/lib/R/library/stats"
#> 

my_sum <- rnorm
find_object(value = my_sum)
#> $name
#> [1] "my_sum"
#> 
#> $envir
#> <environment: 0x55f4190554b0>
#> 

find_object(value = my_sum, from = parent_env())
#> $name
#> [1] "rnorm"
#> 
#> $envir
#> <environment: package:stats>
#> attr(,"name")
#> [1] "package:stats"
#> attr(,"path")
#> [1] "/home/hb/shared/software/CBI/R-4.2.1-gcc9/lib/R/library/stats"
#> 

my_sum <- local(sum)
find_object(value = my_sum)
#> $name
#> [1] "my_sum"
#> 
#> $envir
#> <environment: 0x55f4190554b0>
#> 


my_find <- function(object, envir = parent.frame()) {
  find_object(value = object, from = envir)
}

my_fcn <- local({
  g <- sum  ## this is never found
  function(f = NULL) {
    if (is.null(f)) {
      f <- g  ## this is found first
      my_find(f)
    } else {
      my_find(f, envir = parent.frame()) # skip argument 'f'
    }
  }
})
my_fcn()
#> $name
#> [1] "f"
#> 
#> $envir
#> <environment: 0x55f419c482b8>
#> 
my_fcn(my_sum)
#> $name
#> [1] "my_sum"
#> 
#> $envir
#> <environment: 0x55f4190554b0>
#> 

topenv()
#> <environment: R_GlobalEnv>