Hanjo Odendaal
Hanjo Odendaal

Reputation: 1441

make created variable available in parent environment in r

I am using a function within a function in R to create new variables. What I need is to be able to use these variables in the parent environment, BUT not global.

For instance, one solution is to use the global assignment operator <<-:

f1 <- function(x){

  cat("X is ", x, "\n")
  f2 <- function(){
    cat("X will now be transfromed\n")
    y <<- x + 4 # Use Global assignment
  }

  f2()

  cat("Y is ", y, "\n")
} 
f1(x = 5)

But I have over 20 variables, so this will clutter my workspace and is bad practice.

I was wondering if there is a better solution without having to play with concepts such as vars_to_parent <- new.env().

Is there is some elegant R sorcery where you have a new assignment operator, maybe something silly such as:

`<p-` <- function(){assign variable in such a way that its available in parent}

Which could help you to get these newly created variables to parent environment:

f1 <- function(x){

  cat("X is ", x, "\n")
  f2 <- function(){
    cat("X will now be transfromed\n")
    y <p- x + 4 # New cool assignment operator
  }

  f2()

  cat("Y is ", y, "\n")
} 
f1(x = 5)

Upvotes: 4

Views: 580

Answers (1)

G. Grothendieck
G. Grothendieck

Reputation: 270298

The last line of f will copy all variables in f to the specified environment. Alternately, replace as.list(environment()) with list("a", "b") or to only copy variables beginning with a lower case letter, say, as.list(ls(pattern = "^[a-z]"))

if (exists("a")) rm(a)
if (exists("b")) rm(b)

f <- function(envir = parent.frame()) {
  a <- b <- 1
  invisible( list2env(as.list(environment()), envir) )
}
f()
a
## [1] 1
b
## [1] 1

Rather than inject the variables directly into the parent another possibility which is a bit cleaner is to return the environment itself:

f2 <- function(envir = parent.frame()) {
  a <- b <- 1
  environment()
}
e <- f()
e$a
## [1] 1
e$b
## [1] 1

or return a list by replacing the last statement in f2 with:

list2env(environment())

Upvotes: 3

Related Questions