Encerrando variables dentro del ciclo for
Considere el siguiente fragmento de código que no funciona como la mayoría de la gente podría esperar
#cartoon example
a <- c(3,7,11)
f <- list()
#manual initialization
f[[1]]<-function(x) a[1]+x
f[[2]]<-function(x) a[2]+x
f[[3]]<-function(x) a[3]+x
#desired result for the rest of the examples
f[[1]](1)
# [1] 4
f[[3]](1)
# [1] 12
#attempted automation
for(i in 1:3) {
f[[i]] <- function(x) a[i]+x
}
f[[1]](1)
# [1] 12
f[[3]](1)
# [1] 12
Tenga en cuenta que obtenemos 12 en ambas ocasiones después de intentar "automatizar". El problema es, por supuesto, quei
no está encerrado en el entorno privado de la función. Todas las funciones se refieren a lo mismo.i
en el entorno global (que solo puede tener un valor) ya que un bucle for no parece crear un entorno diferente para cada iteración.
sapply(f, environment)
# [[1]]
# <environment: R_GlobalEnv>
# [[2]]
# <environment: R_GlobalEnv>
# [[3]]
# <environment: R_GlobalEnv>
Así que pensé que podría usar el uso delocal()
yforce()
para capturar eli
valor
for(i in 1:3) {
f[[i]] <- local({force(i); function(x) a[i]+x})
}
f[[1]](1)
# [1] 12
f[[3]](1)
# [1] 12
Pero esto todavía no funciona. Puedo ver que todos tienen entornos diferentes (a través desapply(f, environment)
) sin embargo, parecen estar vacías (ls.str(envir=environment(f[[1]]))
) Compara esto con
for(i in 1:3) {
f[[i]] <- local({ai<-i; function(x) a[ai]+x})
}
f[[1]](1)
# [1] 4
f[[3]](1)
# [1] 12
ls.str(envir=environment(f[[1]]))
# ai : int 1
ls.str(envir=environment(f[[3]]))
# ai : int 3
Así que claramente elforce()
No funciona como esperaba. Estaba asumiendo que capturaría el valor actual dei
en el entorno actual. Es útil en casos como
#bad
f <- lapply(1:3, function(i) function(x) a[i]+x)
#good
f <- lapply(1:3, function(i) {force(i); function(x) a[i]+x})
dóndei
se pasa como un parámetro / promesa, pero esto no debe ser lo que sucede en el ciclo for.
Entonces mi pregunta es: ¿es posible crear esta lista de funciones sinlocal()
y cambio de nombre variable? ¿Hay una función más apropiada queforce()
que capturará el valor de una variable de un marco primario en el entorno local / actual?