更新2 @G. Grothendieck发布了两种方法。第二种方法是在函数内部更改函数环境。这解决了我的过多编码复制的问题。我不确定在将我的脚本制作成包时,这是否是通过CRAN检查的好方法。当我有一些结论时,我会再次更新。
更新
我正在尝试将许多输入参数变量传递给f2
,并且不想在函数内部对每个变量进行索引,例如env$c, env$d, env$calls
,这就是为什么我尝试在f5
和f6
(一个修改后的f2
)中使用with
的原因。然而,assign
在{}
内部与with
不起作用,将assign
移到外部可以完成工作,但在实际情况下,我有几个assign
在with
表达式内部,我不知道如何轻松地将它们移出with
函数。
以下是一个示例:
## In the <environment: R_GlobalEnv>
a <- 1
b <- 2
f1 <- function(){
c <- 3
d <- 4
f2 <- function(P){
assign("calls", calls+1, inherits=TRUE)
print(calls)
return(P+c+d)
}
calls <- 0
v <- vector()
for(i in 1:10){
v[i] <- f2(P=0)
c <- c+1
d <- d+1
}
return(v)
}
f1()
函数 f2
嵌套在 f1
内部,当调用 f2
时,它会在环境 environment(f1)
中查找变量 calls,c,d
。这正是我想要的。
然而,当我想在其他函数中使用 f2
时,我将定义此函数在全局环境中,称其为 f4
。
f4 <- function(P){
assign("calls", calls+1, inherits=TRUE)
print(calls)
return(P+c+d)
}
这不可行,因为它将在全局环境中查找calls,c,d
,而不是在调用函数的函数内部查找。例如:
f3 <- function(){
c <- 3
d <- 4
calls <- 0
v <- vector()
for(i in 1:10){
v[i] <- f4(P=0) ## or replace here with f5(P=0)
c <- c+1
d <- d+1
}
return(v)
}
f3()
安全的做法应该是在f4
的输入参数中定义calls,c,d
并将这些参数传递给f4
。然而,在我的情况下,有太多变量要传递给这个函数f4
,最好能够将它作为一个环境传递,并告诉f4
在调用f3
时只查找environment
内部,而不要查找全局环境(environment(f4)
)。
我现在解决的方法是将环境用作列表,并使用with
函数。
f5 <- function(P,liste){
with(liste,{
assign("calls", calls+1, inherits=TRUE)
print(calls)
return(P+c+d)
}
)
}
f3 <- function(){
c <- 3
d <- 4
calls <- 0
v <- vector()
for(i in 1:10){
v[i] <- f5(P=0,as.list(environment())) ## or replace here with f5(P=0)
c <- c+1
d <- d+1
}
return(v)
}
f3()
然而,现在assign("calls", calls+1, inherits=TRUE)
不能像原来那样正常工作,因为assign
没有修改原始对象。变量calls
与最优化函数相关,在这个函数中,目标函数是f5
。这就是我使用assign
而不是将calls
作为输入参数传递的原因。对我来说,使用attach
也不清楚。以下是我纠正assign
问题的方法:
f7 <- function(P,calls,liste){
##calls <<- calls+1
##browser()
assign("calls", calls+1, inherits=TRUE,envir = sys.frame(-1))
print(calls)
with(liste,{
print(paste('with the listed envrionment, calls=',calls))
return(P+c+d)
}
)
}
########
##################
f8 <- function(){
c <- 3
d <- 4
calls <- 0
v <- vector()
for(i in 1:10){
##browser()
##v[i] <- f4(P=0) ## or replace here with f5(P=0)
v[i] <- f7(P=0,calls,liste=as.list(environment()))
c <- c+1
d <- d+1
}
f7(P=0,calls,liste=as.list(environment()))
print(paste('final call number',calls))
return(v)
}
f8()
我不确定在R中应该如何完成这个任务。我是否朝着正确的方向前进,特别是在通过CRAN检查时?有人可以给我一些提示吗?
f2
中的所有变量,即不写env$
,这就是为什么我尝试使用with
的原因。我希望能够在f2
中修改外部的calls
,但不更改当前环境中的其他变量。我将更新问题。 - Zhenglei