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.
当尝试使用lapply创建类似函数的列表时,我发现列表中的所有函数都是相同的,并且等于最终元素应该是什么。
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)?
这里发生了什么,我怎样才能得到我想要的结果(列表中的正确功能)?
2 个解决方案
#1
20
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:
R通过承诺,而不是价值本身。承诺在第一次评估时被强制,而不是在传递时,并且到那时索引已经改变,如果使用问题中的代码。可以按如下方式编写代码,以便在调用外部匿名函数时强制执行promise,并使读者清楚:
pl <- lapply(1:3, function(y) { force(y); function(x) pow(x,y) } )
#2
7
This is no longer true as of R 3.2.0!
从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.
诸如apply函数和Reduce()之类的高阶函数现在强制对它们应用的函数进行参数化,以消除惰性求值与闭包中的变量捕获之间的不良交互。
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
#1
20
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:
R通过承诺,而不是价值本身。承诺在第一次评估时被强制,而不是在传递时,并且到那时索引已经改变,如果使用问题中的代码。可以按如下方式编写代码,以便在调用外部匿名函数时强制执行promise,并使读者清楚:
pl <- lapply(1:3, function(y) { force(y); function(x) pow(x,y) } )
#2
7
This is no longer true as of R 3.2.0!
从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.
诸如apply函数和Reduce()之类的高阶函数现在强制对它们应用的函数进行参数化,以消除惰性求值与闭包中的变量捕获之间的不良交互。
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