当我创建一个循环来将函数包装在列表中时,输入列表中的最后一个函数总是用于所有包装调用。
wrapper <- function(f)function()f()
fs <- list(f = function()"call f", g = function()"call g")
ws <- list()
for(n in names(fs))
ws[[n]] <- wrapper(fs[[n]])
ws$f()
[1] "call g"
我在上面的代码中预计"call f"
,但实际上它返回了"call g"
。
有人能解释我为什么会这样吗?
标志是什么,或者在哪种情况下我必须强制评估以避免类似的
非常感谢
答案 0 :(得分:1)
最后,我想出了自己的答案
发生这种情况有两个原因:for
循环没有自己的环境,而wrapper
懒惰地评估其参数f
。
第一个原因:for
循环使用全局环境
出于后一个原因:将wrapper
更改为function(f){force(f); function()f()}
会导致我在问题中的预期结果。
详细说明:
问题中的循环被解释为
for(n in names(fs)){
tmp <- fs[[n]]
ws[[n]] <- wrapper(tmp)
}
因为wrapper
懒惰地评估参数f
,所以它会将f
保留在其执行环境中,但不会保留其值。相反,它会在需要时记住如何评估f
。换句话说,它会记住对(<environment: R_GlobalEnv>, "tmp")
。
检查以下代码会清除我说的所有内容。
tmp <- f
wf <- wrapper(tmp)
tmp <- g
wf()
[1] "call g"
但
tmp <- f
wf <- wrapper(tmp)
wf()
[1] "call f"
tmp <- g
wf()
[1] "call f"
后一个代码在第二次调用中打印"call f"
,因为f
被评估并存储在wrapper
的环境中,无需再次评估(成为g
})