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.