在for循环中包含变量 [英] Enclosing variables within for loop
问题描述
#cartoon示例
a < - c(3,7,11)
f < - list()
#manual initialization
f [[1]] <-function(x) (x)a [2] + x
f [[3]]< - 函数(x)a [3] + x
#desired result for the other examples
f [[1]](1)
#[1] 4
f [[3]](1)
#[1] 12
#attempted automation
for(i in 1:3){
f [[i]] < - function(x)a (1)
$ b $ [$ 1]
$ [1] b#[1] 12
请注意,在我们尝试自动化之后,当然,问题在于 i
没有包含在函数的私有环境中。所有的函数在全局环境(只能有一个值)中引用相同的 i
,因为for循环似乎并没有为每次迭代创建不同的环境。 b
$ b $ pre $ $ $ $ $ $
$<环境:R_GlobalEnv>
#[[2]]
#< environment:R_GlobalEnv>
#[[3]]
#< environment:R_GlobalEnv>
所以我尽管可以使用 local() 和
force()
来捕捉 i
值
for(i in 1:3){
f [[i]]< - local({force(i); function(x)a (1)
$
$ bf [[1]](1)
#[1] 12
f [[3]](1)
#[1] 12
但是这仍然不起作用。我可以看到它们都有不同的环境(通过 sapply(f,environment)
),但它们看起来是空的( ls.str(envir = environment (F [[1]]))
)。 (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
显然, force()
不能像我所期望的那样工作。我假设它会捕获 i
当前值到当前环境中。它在
#bad
f < - lapply(1:3,函数(i)函数(x)a [i] + x)
#good
f < - lapply(1:3,function(i){force(i); function(x)a [i] + x} )
其中 i
作为参数传递/ promise,但是这肯定不是在for循环中发生的事情。
所以我的问题是:可以创建这个函数列表,而不需要 local()
和变量重命名?有没有比 force()
更适合的函数,它将从父框架的变量捕获到本地/当前环境中?
这不是一个完整的答案,部分是因为我不确定问题到底是什么(即使我发现它很有趣!
相反,我只提供了两个替代的
- 循环。他们已经帮助澄清了我脑海中的问题(特别是帮助我首次明白为什么 force()
在调用 lapply()
)。我希望他们也会帮助你。
首先,这是一个更接近您的功能 lapply()
call,它的工作原理和它一样:
a < - c(3, 7,11)
f < - list()
##`for`loop等效于:
## f < - lapply(1:3,function(i ){{(i); function(x)a [i] + x})
for(i in 1:3){
f [[i]] < - {X < - function (i){force(i);函数(x)a [i] + x}; X(i)}
}
f [[1]](1)
#[1] 4
其次,这是一个使用 local()
但不会(严格地或字面地说)重命名我
。但是,它通过将它的一个副本添加到当地环境中来重新它。从某种意义上来说,它与你的对于
-loop只有平凡的不同,但是通过把注意力集中在 i
的作用域,而不是它的名字,我认为这有助于揭露你的问题背后的真实问题。
a < - c 3,7,11)
f < - list()
(i in 1:3){
f [[i]]< - local({i< -i;函数(x)a [i] + x})
}
f [[1]](1)
#[1] 4
So consider the following chunk of code which does not work as most people might expect it to
#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
Note that we get 12 both times after we attempt to "automate". The problem is, of course, that i
isn't being enclosed in the function's private environment. All the functions refer to the same i
in the global environment (which can only have one value) since a for loop does not seem to create different environment for each iteration.
sapply(f, environment)
# [[1]]
# <environment: R_GlobalEnv>
# [[2]]
# <environment: R_GlobalEnv>
# [[3]]
# <environment: R_GlobalEnv>
So I though I could get around with with the use of local()
and force()
to capture the i
value
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
but this still doesn't work. I can see they all have different environments (via sapply(f, environment)
) however they appear to be empty (ls.str(envir=environment(f[[1]]))
). Compare this to
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
So clearly the force()
isn't working like I was expecting. I was assuming it would capture the current value of i
into the current environment. It is useful in cases like
#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})
where i
is passed as a parameter/promise, but this must not be what's happening in the for-loop.
So my question is: is possible to create this list of functions without local()
and variable renaming? Is there a more appropriate function than force()
that will capture the value of a variable from a parent frame into the local/current environment?
This isn't a complete answer, partly because I'm not sure exactly what the question is (even though I found it quite interesting!).
Instead, I'll just present two alternative for
-loops that do work. They've helped clarify the issues in my mind (in particular by helping me to understand for the first time why force()
does anything at all in a call to lapply()
). I hope they'll help you as well.
First, here is one that's a much closer equivalent of your properly function lapply()
call, and which works for the same reason that it does:
a <- c(3,7,11)
f <- list()
## `for` loop equivalent of:
## f <- lapply(1:3, function(i) {force(i); function(x) a[i]+x})
for(i in 1:3) {
f[[i]] <- {X <- function(i) {force(i); function(x) a[i]+x}; X(i)}
}
f[[1]](1)
# [1] 4
Second, here is one that does use local()
but doesn't (strictly- or literally-speaking) rename i
. It does, though, "rescope" it, by adding a copy of it to the local environment. In one sense, it's only trivially different from your functioning for
-loop, but by focusing attention on i
's scope, rather than its name, I think it helps shed light on the real issues underlying your question.
a <- c(3,7,11)
f <- list()
for(i in 1:3) {
f[[i]] <- local({i<-i; function(x) a[i]+x})
}
f[[1]](1)
# [1] 4
这篇关于在for循环中包含变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!