R保留列表循环中的最后一个变量的奇怪行为?

问题描述 投票:5回答:1

当我创建一个循环来将函数包装在列表中时,输入列表中的最后一个函数总是用于所有包装调用。

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"

谁能解释我为什么会这样?

什么是标志,或者在哪种情况下我必须强制进行评估以避免类似的情况

非常感谢你

r functional-programming lazy-evaluation
1个回答
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

© www.soinside.com 2019 - 2024. All rights reserved.