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

Jam*_*mes 14 closures r anonymous-function lapply

当尝试使用时创建类似函数的列表时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>
Run Code Online (Sandbox Code Playgroud)

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

pl[[1]](2)
[1] 8
pl[[2]](2)
[1] 8
pl[[3]](2)
[1] 8
Run Code Online (Sandbox Code Playgroud)

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

G. *_*eck 20

R通过承诺,而不是价值本身.承诺在首次评估时被强制,而不是在它被传递时,并且如果使用了问题中的代码,那么索引已经改变了.可以按如下方式编写代码,以强制在调用外部匿名函数时使用promise,并使读者清楚:

pl <- lapply(1:3, function(y) { force(y); function(x) pow(x,y) } )
Run Code Online (Sandbox Code Playgroud)


jhi*_*hin 7

从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
Run Code Online (Sandbox Code Playgroud)