从lapply返回匿名函数-出了什么问题?

14

尝试使用lapply创建一系列相似的函数时,我发现列表中的所有函数都是相同的,并且等于最后一个元素应该是什么。

考虑以下内容:

pow <- function(x,y) x^y
pl <- lapply(1:3,function(y) function(x) pow(x,y))
pl
[[1]]
function (x) 
pow(x, y)
<environment: 0x09ccd5f8>

[[2]]
function (x) 
pow(x, y)
<environment: 0x09ccd6bc>

[[3]]
function (x) 
pow(x, y)
<environment: 0x09ccd780>

当您尝试评估这些函数时,您会得到相同的结果:

pl[[1]](2)
[1] 8
pl[[2]](2)
[1] 8
pl[[3]](2)
[1] 8

这里发生了什么事情,我该如何获得我想要的结果(即列表中正确的函数)?


我不确定你的目标是什么。也许可以尝试使用 pl <- function(x,y) lapply(y,function(y) pow(x,y)); pl(2,1:3) - Roland
这些由Ross Ihaka(RCore)撰写的笔记可能会有所帮助(特别是关于惰性求值的部分)。www.stat.auckland.ac.nz/~ihaka/downloads/Waikato-WRUG.pdf - Ricardo Saporta
请注意,自R 3.2.0起,这已不再是真实的情况,请参见我下面的答案。 - Eike P.
2个回答

20

R传递promises,而不是值本身。 当第一次评估承诺时,它被强制执行,而不是在传递时,如果使用问题中的代码,则此时索引已更改。 可以按以下方式编写代码,force在调用外部匿名函数时强制执行该承诺,并使读者清楚:

pl <- lapply(1:3, function(y) { force(y); function(x) pow(x,y) } )

谢谢,了解这个陷阱的工作方式很好。我将来必须记住这一点。 - James

8
自 R 3.2.0 起,这已不再是真实情况了!
相应的变更日志中的行如下:
高阶函数(例如 apply 函数和 Reduce())现在强制要求它们应用的函数参数,以消除惰性求值和闭包中变量捕获之间的不良交互。
确实如此:
pow <- function(x,y) x^y
pl <- lapply(1:3,function(y) function(x) pow(x,y))
pl[[1]](2)
# [1] 2
pl[[2]](2)
# [1] 4
pl[[3]](2)
# [1] 8

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接