在for循环中包含变量 [英] Enclosing variables within for loop

查看:164
本文介绍了在for循环中包含变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,请考虑以下代码块,它不会像大多数人所期望的那样工作。

  #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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆