Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

overwrite variable in parent function from inner function without making variable outside parent function

Tags:

r

I am trying to overwrite variable a in 'outer_func' with a value from 'inner_func'. I do not want it to produce a variable a outside of the function 'outer_func'.

inner_func <- function(){
  a <<- 30
}

outer_func <- function(){
  a <- 10
  inner_func()
  print(a)
}

outer_func()

The output is 10, but it should be 30.

like image 447
user3651829 Avatar asked Dec 21 '25 03:12

user3651829


2 Answers

You can use assign with the parent.frame() (parent.frame() s the environment of the outer function, parent.frame(2) would be global environment in this case):

inner_func <- function(){
  assign("a", 30, envir = parent.frame())
}

outer_func <- function(){
  a <- 10
  inner_func()
  print(a)
}

outer_func()

However be careful, because using side effects like makes the code much more complicated, and usually is inadvisable.

like image 101
Zygmunt Zawadzki Avatar answered Dec 22 '25 18:12

Zygmunt Zawadzki


Here are 3 alternatives. (1) makes no changes to inner_func and (3) makes no changes to outer_func.

1) copy and reset environment of inner_func Make a copy of inner_func within outer_func and coerce the current environment to the copy. No changes are made to inner_func and only one line is added to outer_func and that both makes the copy and changes its environment.

outer_func <- function() {
  a <- 10
  environment(inner_func) <- environment() 
  inner_func()
  print(a)
}

outer_func()
## [1] 30

2) nest inner_func in outer_func Another way to do this is to nest inner_func within outer_func.

outer_func <- function() {

  inner_func <- function() {
    a <<- 30
  }

  a <- 10
  inner_func()
  print(a)
}

outer_func()
## [1] 30

3) pass environment via arg Another way is to pass the environment where a is located to inner_func via an argument. By making the parent frame the default value of that argument we can avoid having to make any changes to outer_func.

inner_func <- function(envir = parent.frame()) {
  envir$a <- 30
}

outer_func <- function() {
  a <- 10
  inner_func()
  print(a)
}

outer_func()
## [1] 30

Note

Any of these can be extended to set particular matrix elements if a is defined, say, as this in outer_func.

a <- matrix(1:4, 2)

In (1) and (2) modify inner_func to use, for example:

a[1,1] <<- 30

and in (3) use, for example, this in inner_func:

envir$a[1,1] <- 30
like image 33
G. Grothendieck Avatar answered Dec 22 '25 20:12

G. Grothendieck



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!