使用 with() 更新函数内的列表不会 return 更新输出

Using with() to update list within a function doesn't return updated output

如何在函数中使用with()(或替代方法)以便在执行函数后更新并返回数据?我知道正在调用数据(在我的例子中是我想在每个时间步更新的列表中的对象和执行此操作的输入参数),正在执行 for-loop 中的命令但没有更新数据回来。为什么会这样?我是否遗漏了有关 with() 函数的内容?

我也尝试了 within()within.list() ,其中 returns 相同的输出是初始化时的这个列表。

#~ input parameters
xPRM <- list()
xPRM$n_ts   <- 4
xPRM$n_yrs  <- 1
xPRM$n_x1   <- 25
xPRM$n_x2   <- 10
xPRM$n_x3   <- 5

set.seed(1)
my_func <- function(X){
        #~ lists to collect data after functions have been executed in each time-step
        list1    <- vector(mode = "list", length = X$n_ts*X$n_yrs)
        list2    <- vector(mode = "list", length = X$n_ts*X$n_yrs)
        # etc.
        
        #~ list for compartments (computations in each time step will be in these compartments)
        comp.1    <- list()
        comp.2    <- list()
        # etc. 
        
        #~ comp.1 initialisation
        comp.1$ts <- rep(0, X$n_x1)                                      
        comp.1$yr <- rep(0, X$n_x1)
        comp.1$v1 <- rnorm(X$n_x1, X$n_x2, X$n_x3)        
        comp.1$v2 <- rep(0, X$n_x1)
        
        with(c(comp.1, X), 
                    for(i in 1:n_ts*n_yrs){
                            ts <- i
                            yr <- ceiling(i/n_ts)
                            
                            v1[v1 >= 5]  <- v1[v1 >= 5]^(n_x3/i)    #~ do something 
                            v2[v1 >= 10] <- v2[v1 >= 10] + n_x3*i   #~ do something again 
                            #print(v2)                              #~ will show that the somethings are being done


                            #~Return data at end of time step
                            list1[[i]] <- comp.1
                            # list2[[i]] <- comp.2
                            # etc.
                    }
        )
        all_lists <- list(A = list1, B = list2
                          # etc.,
        )
        all_lists
        # list1
        # comp.1
}

my_func(X = xPRM)

编辑

可以使用以下代码生成预期输出的示例:

set.seed(1)
#~ lists to collect data after functions have been executed in each time-step
list1    <- vector(mode = "list", length = X$n_ts*X$n_yrs)
list2    <- vector(mode = "list", length = X$n_ts*X$n_yrs)
# etc.

#~ comp.1 initialisation
comp.1$ts <- rep(0, xPRM$n_x1)                                      
comp.1$yr <- rep(0, xPRM$n_x1)
comp.1$v1 <- rnorm(xPRM$n_x1, xPRM$n_x2, xPRM$n_x3)        
comp.1$v2 <- rep(0, xPRM$n_x1)
for(i in 1:xPRM$n_ts*xPRM$n_yrs){
        comp.1$ts <- i
        comp.1$yr <- ceiling(i/xPRM$n_ts)
        
        comp.1$v1[comp.1$v1 >= 5]  <- comp.1$v1[comp.1$v1 >= 5]^(xPRM$n_x3/i)    #~ do something 
        comp.1$v2[comp.1$v1 >= 10] <- comp.1$v2[comp.1$v1 >= 10] + xPRM$n_x3*i   #~ do something again 
        
        #~Return data at end of time step
        list1[[i]] <- comp.1
        # list2[[i]] <- comp.2
        # etc.
}
all_lists <- list(A = list1, B = list2
                  # etc.,
)
#~ Expected output
all_lists

问题在于 with() 在调用它时创建的本地环境中执行其所有操作,包括赋值。这意味着 list1 不会在 with() 范围之外更新。

来自with() docs:

with is a generic function that evaluates expr in a local environment constructed from data.
...
Note that assignments within expr take place in the constructed environment and not in the user's workspace.
...
For interactive use this is very effective and nice to read. For programming however, i.e., in one's functions, more care is needed, and typically one should refrain from using with(), as, e.g., variables in data may accidentally override local variables, see the reference.

您可以坚持使用 <<- 赋值运算符在全局上下文中更新 list1。 (请注意,应谨慎使用这种强制全局分配 - 请参阅讨论 here。)

此外,comp.1 实际上并没有在它自己的 with() 上下文中更新,因此您需要在完成计算后构建一个列表并将其存储在 list1[[i]].

像这样:

list1[[i]] <<- list(ts = ts, yr = yr, v1 = v1, v2 = v2)

完成这些更改后,with() 实施的输出与您的预期输出完全匹配。