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

这里发生了什么,我怎样才能得到我想要的结果(列表中的正确函数)?

4

2 回答 2

20

R 通过promises,而不是值本身。承诺在第一次评估时被强制执行,而不是在通过时,如果使用问题中的代码,到那时索引已经改变。代码可以写成如下,在调用外部匿名函数时强制执行承诺,并让读者清楚:

pl <- lapply(1:3, function(y) { force(y); function(x) pow(x,y) } )
于 2013-04-01T11:26:32.960 回答
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
于 2015-04-22T02:45:14.343 回答