【发布时间】:2013-04-14 08:08:28
【问题描述】:
我正在阅读 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 在您第一次调用加法器时被懒惰地评估 职能。至此,循环完成,最终值为 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”这句话感到特别困惑。什么循环?什么最终值,在哪里?一定是我想念的简单的东西,但我只是看不到它。提前非常感谢。
【问题讨论】:
-
请注意,自 R 3.2.0 起,此问题的答案已更改,请参阅下面的答案。
-
对@jhin 评论的补充:虽然
lapply()在最近的R 中发生了变化,但打算在lapply()所在的任何地方使用的函数purrr::map()仍然表现得像旧的lapply()相对于闭包的共享环境。但是,我不会指望purrr::map()的这种“时代错误”会继续存在,因为它可能会在未来的版本中得到纠正。 -
@jhin 实际上,我猜 hadley 的教程是直接从 github 构建的,所以在 R 3.2.0 之后阅读它现在很奇怪,因为该版本使该教程中关于惰性评估的整个部分变得毫无意义:没有与
adders和adders2的输出有更大的不同!
标签: r lazy-evaluation