r - R闭包范围
问题描述
我试图理解 R 中的闭包。
有人可以解释一下为什么这段代码(1):
vars <- c("one", "two")
funcs <- list()
for (v in vars) {
funcs[[length(funcs) + 1]] <- function() {
print(v)
}
}
funcs[[1]]()
funcs[[2]]()
返回
[1] "two"
[1] "two"
但以下代码(2):
vars <- c("one", "two")
funcs <- list()
getFunc <- function(v) {
v_i <- v
function() {
print(v_i)
}
}
for (v in vars) {
funcs[[length(funcs) + 1]] <- getFunc(v)
}
funcs[[1]]()
funcs[[2]]()
返回:
[1] "one"
[1] "two"
此外,此代码仍然只打印“两个”(3):
vars <- c("one", "two")
funcs <- list()
for (v in vars) {
v_i <- v
funcs[[length(funcs) + 1]] <- function() {
print(v_i)
}
}
funcs[[1]]()
funcs[[2]]()
这也只打印“两个”(4):
vars <- c("one", "two")
funcs <- list()
getFunc <- function(v) {
function() {
print(v)
}
}
for (v in vars) {
funcs[[length(funcs) + 1]] <- getFunc(v)
}
funcs[[1]]()
funcs[[2]]()
我猜 v 被重用了,所以它总是指向内存中的同一个空间。但是我们能否确定 v 将始终是列表的最后一个值——它会持续存在还是易变?
(3) 意味着给其他变量赋值是不够的,它必须在单独的函数中。
(4) 表示函数的参数也被重用。
解决方案
在v
全局环境中任何时候都只有一个值但是随着for
循环的变化而变化的值v
。在第一次迭代v
中是"one"
,在第二次迭代中是"two"
,并且由于v
随后没有更改,因此它保持在 value "two"
。现在,
1)在第一种情况下,当您调用funcs[[1]]()
它时,它会v
在funcs[[1]]
其中查找并且找不到它,因此它environment(funcs[[1]])
会在全局环境中查找。
environment(funcs[[1]])
## <environment: R_GlobalEnv>
v
运行时全局环境中的值funcs[[1]]
是“二”,因此它会打印出来。
2)在第二个示例中,当您调用funcs[[1]]()
它时,它会查找v_i
infuncs[[1]]
并且找不到它,所以它会再次查找,environent(funcs[[1]])
但现在的环境funcs[[1]]
是getfunc
. 每次getfunc
运行该环境都会有所不同。无论如何,在那个环境v_i
中都有价值"one"
,所以它会打印出来。
environment(funcs[[1]])
## <environment: 0x00000000097418d0>
3)第三个例子和第一个例子基本相同。 v_i
处于全局环境中,并且"two"
在运行时具有值funcs[[1]()
。
4)在第四个例子中environment(funcs[[1]])
是运行时环境getfunc
;然而,因为在被调用之前还没有访问到的v
参数,所以仍然是一个未评估的承诺。当最终被调用时,它需要使用promise 被评估并且此时是.getfunc
funcs[[1]]
v
funcs[[1]]
v
v
"two"
推荐阅读
- apache-spark - spark sql:读取镶木地板分区文件时超出了 GC 开销限制
- distinct - 除了,在 MDX 中不同
- python - 如何从关键位置的值中获取国家/地区?
- javascript - javascript 如何通过组合两个 JSON 来创建一个 JSON
- python - Python从网络获取ips和macs
- redux - 在 Redux 中间件中是否应该总是最后调用“下一个”?
- hyperledger-fabric - Hyperledger Composer 车辆生命周期网络
- sql - SQLite 将由逗号分隔的值的字符串转换为列表
- php - 文本上的 PHP preg_match 不起作用
- kubernetes - 由于服务器向 HTTPS 客户端提供了 HTTP 响应,Kubernetes oc rsync 不起作用