Home > Mobile >  List is not updated when run inside a function
List is not updated when run inside a function

Time:10-07

Problem

With this toy problem, I want to understand why a list is not updated when a function calls another function. The same list is updated if I run the code outside of the second function.

Reproducible Example:

The following function updates a previously empty list SControlModelStates():

library(pracma)
func_1 <- function(VTimeStamp,
                   iSample,
                   SParameters){
  
  # is this the first time step?
  if (pracma::isempty(SControlModelStates)){ 
    
    
    stopifnot(iSample == 1)
    
    
    # set default values for any unspecified model parameters
    if (!('my_param' %in% names(SParameters))){
      SParameters[['my_param']] <- 5
    }
    
    SControlModelStates[['my_val']] <- rep(0, length(VTimeStamp))
    
  } else {
    
    # this is not the first time step
    SControlModelStates[['my_val']][iSample] <- SControlModelStates[['my_val']][iSample-1]   SParameters[['my_param']]
  }
  
  
  
  res <- list('SParameters' = SParameters,
              'SControlModelStates' = SControlModelStates)
  
  res
  
}

Running the function:

When I run the above function, it successfully updates SControlModelStates():

SControlModelStates <- list()
Parameters <- list()
VTimeStamp <- 1:5


for (i in 1:length(VTimeStamp)){
  
  foo <- func_1 (VTimeStamp,
                     i,
                     Parameters)
  
  Parameters <- foo[["SParameters"]]
  SControlModelStates <- foo[["SControlModelStates"]]
}


> SControlModelStates
$my_val
[1]  0  5 10 15 20

Calling the above function in another function produces an error:

After restarting R I did the following:

## Function definition
func_2 <- function(VTimeStamp){
  
  SControlModelStates <- list()
  Parameters <- list()
  VTimeStamp <- VTimeStamp
  
  
  
  for (i in 1:length(VTimeStamp)){
    
    foo <- func_1 (VTimeStamp,
                   i,
                   Parameters)
    
    Parameters <- foo[["SParameters"]]
    SControlModelStates <- foo[["SControlModelStates"]]
  }
  
  return(SControlModelStates[["my_val"]])
}


## Running the function:
> func_2(1:5)
 Error in pracma::isempty(SControlModelStates) : 
object 'SControlModelStates' not found

This indicates that SControlModelStates() is not updated when iSample == i == 1. It remains empty when i==2. How can I fix func_2 to resolve this issue?

CodePudding user response:

Your problem is one of variable scope.

The for loop run as is works because you define SControlModelStates as a global variable and func_1 can access it.

When you run func_2 then func_1 doesn't have access to the calling environment (func_1 and global) but only the environment it was defined in (global) but the global environment doesn't have a variable SControlModelStates in a clean R runtime.

If you want to reference an existing SControlModelStates you either need to pass it as a parameter to func_1 (preferred) or use a global variable.

  •  Tags:  
  • r
  • Related