解释一个懒惰的评价怪癖

时间:2013-04-21 09:51:03

标签: r lazy-evaluation

我正在阅读Hadley Wickhams关于Github的书,特别是this part on lazy evaluation。在那里,他给出了一个懒惰评估结果的例子,在add/adders函数的部分。让我引用一点:

  

当使用lapply或循环创建闭包时,[懒惰评估]很重要:

add <- function(x) {
  function(y) x + y
}
adders <- lapply(1:10, add)
adders[[1]](10)
adders[[10]](10)
     第一次调用其中一个加法器时,

会被懒惰地评估   功能。此时,循环完成并且最终值为   x是10.因此,所有加法器函数都会将10加到它们上面   输入,可能不是你想要的!手动强制进行评估修复   问题:

add <- function(x) {
  force(x)
  function(y) x + y
}
adders2 <- lapply(1:10, add)
adders2[[1]](10)
adders2[[10]](10)

我似乎并不理解这一点,而且解释很少。有人可以详细说明这个特定的例子,并解释那里发生了什么?我特别对句子感到困惑“此时,循环完成,x的最终值为10”。什么循环?什么最终价值,在哪里?一定是简单的我想念,但我只是没有看到它。非常感谢。

2 个答案:

答案 0 :(得分:57)

从R 3.2.0开始,这已经不再适用了!

change log中的相应行显示:

  

高阶函数,例如apply函数和Reduce()   强制论证它们适用的函数以消除   惰性评估和变量捕获之间的不良交互   在关闭。

确实:

add <- function(x) {
  function(y) x + y
}
adders <- lapply(1:10, add)
adders[[1]](10)
# [1] 11
adders[[10]](10)
# [1] 20

答案 1 :(得分:35)

目标:

adders <- lapply(1:10, function(x)  add(x) )

是创建一个add函数列表,第一个添加1到它的输入,第二个添加2,等等。懒惰评估使R等待真正创建加法器函数,直到你真正开始调用函数。问题是在创建第一个加法器函数后,x循环增加lapply,结束值为10.当您调用第一个加法器函数时,延迟评估现在构建函数,获取x的值。问题是原始x不再等于1,而是等于lapply循环末尾的值,即10。

因此,延迟评估会导致所有加法器函数等到lapply循环完成后才真正构建函数。然后他们用相同的值构建他们的函数,即10. Hadley建议的解决方案是强制x直接评估,避免延迟评估,并使用正确的x值获取正确的函数。 / p>