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

当试图使用lapply创build一个类似函数的列表时,我发现列表中的所有函数都是相同的,并等于最终的元素应该是什么。

考虑以下几点:

 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> 

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

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

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

R通过承诺 ,而不是价值本身。 这个承诺在第一次被评估的时候是被强制的,而不是在它被传递的时候被强制的,到那个时候如果使用了问题中的代码的话索引已经改变了。 代码可以写成如下的forms来强制在外部匿名函数被调用时的承诺,并向读者说明:

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

从R 3.2.0开始,这不再是真的!

更改日志中的相应行显示如下:

诸如apply函数和Reduce()之类的高阶函数现在强加参数给它们所应用的函数,以消除懒惰评估和闭包中的variables捕获之间的不期望的交互作用。

事实上:

 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