Question is in regards to validating the existence of an environment, and if not found either create the enviornment, or return the variable name passed for whatever reason. Essentially this is a function I'm using in a series of unsupervised functions to determine assignment paths for objects, and functions that are returned in response to observed variables returned from outside functions etc.
My function works fine for all intensive purposes I have tested, but I know I'm forgetting something very basic that makes the use of the workaround completely unneccesary.
The issue is the x variable, which represents the name of the environment, needs to be accepted either as a quoted character string, or nonquoted. I use this method in a lot of my functions, but for some reason I was finding a lot of errors applying the same system to this one. Here's my example... please someone show me the laughably simple method I have forgotten or can't find that makes this as ridiculous as I feel it is.
env.ensure <- function(x = NULL, create_if_not = TRUE, silent = FALSE){
chk <- tryCatch(x, error = function(e){
# Possibly the cheapest, ugliest work-around I've ever pulled...
(gsub("^(.*?)object '|' not found>$","",capture.output(e)))
})
if(!is.environment(chk)){
if(!create_if_not){
return(chk)
}else {
assign(chk, new.env(), envir = .GlobalEnv) %>% (function(x){
if(typeof(x) == "environment"){
point <- as.environment(x)
if(!silent){
return(point)
}
}
})
}
}else {
point <- as.environment(chk)
if(!silent){
return(point)
}
}
}
For brevity here are the tests I've run through so far:
#' # From the console
#' > exists(silly_stuff) ## Error in exists(silly_stuff): object 'silly_stuff' not found
#'
#' # Now passed as a non quoted variable
#' > env.ensure(.silly_things)
#' <environment: 0x00000000160895e8>
#' #' > find('.silly_things')
#' [1] ".GlobalEnv"
#' > rm(.silly_things)
#'
#' # No output
#' > env.ensure(silly_stuff, silent = TRUE)
#' > rm(silly_stuff)
#'
#' # with output
#' > env.ensure(mte_shat, silent = FALSE)
#' <environment: 0x00000000268e5298>
#' > rm(mte_shat)
#'
#' # Output with quoted variable
#' > env.ensure("mte_shat", silent = FALSE)
#' <environment: 0x00000000268bd7e8>
#' > rm(mte_shat)
#'
#' # Output the variable passed, and don't create the environment
#'
#' > env.ensure(".mte_shat", silent = FALSE, create_if_not = FALSE)
#' [1] ".mte_shit"
#'
#' > env.ensure(.gd, silent = TRUE)
#' > find('.gd')
#' [1] ".GlobalEnv"
#'
#'
A use case example using base package data
A <- list(env_name = "base_data", autos = mtcars, population = uspop,
expenses = USPersonalExpenditure)
saveRDS(A,"my_data.rds")
readRDS('my_data.rds') %>% (function(x){
list2env(x[grep('env_name$', names(x), invert = TRUE)],
envir = env.ensure(x[['env_name']], silent = TRUE))
})
names(base_data)
[1] "autos" "expenses" "population"
also would like to point out I use deparse(substitute (...)) / eval (parse (text = ...)) in similar situations but for some reason I couldn't get it to behave with environment setting...