【问题标题】:Strange behaviour that R retains last variable in list loop?R在列表循环中保留最后一个变量的奇怪行为?
【发布时间】:2018-06-05 14:05:46
【问题描述】:

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

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"

谁能解释一下为什么会这样?

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

非常感谢

【问题讨论】:

  • 我怀疑罪魁祸首是懒惰的评价。尝试在你现在的代码之前在你的循环中使用force(n)
  • 奇怪的是,ws &lt;- lapply(fs, wrapper); ws$f() 有效
  • @alistaire AFAIK, lapply 对列表的每个元素执行force。虽然我的循环没有
  • @Dason: force(n) 在循环中 not 工作。 force(f)wrapper 工作,而不是

标签: r functional-programming lazy-evaluation


【解决方案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。换句话说,它记住了(&lt;environment: R_GlobalEnv&gt;, "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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-23
    相关资源
    最近更新 更多