Returning anonymous functions from lapply - what is going wrong?

我的未来我决定 提交于 2019-11-26 08:25:25

问题


When trying to create a list of similar functions using lapply, I find that all the functions in the list are identical and equal to what the final element should be.

Consider the following:

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>

When you try to evaluate these functions you get identical results:

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

What is going on here, and how can I get the result I desire (the correct functions in the list)?


回答1:


R passes promises, not the values themselves. The promise is forced when it is first evaluated, not when it is passed, and by that time the index has changed if one uses the code in the question. The code can be written as follows to force the promise at the time the outer anonymous function is called and to make it clear to the reader:

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



回答2:


This is no longer true as of R 3.2.0!

The corresponding line in the change log reads:

Higher order functions such as the apply functions and Reduce() now force arguments to the functions they apply in order to eliminate undesirable interactions between lazy evaluation and variable capture in closures.

And indeed:

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


来源:https://stackoverflow.com/questions/15742177/returning-anonymous-functions-from-lapply-what-is-going-wrong

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!