5

我不确定承诺在 R 中做了什么

如果一个人跑

a = lapply(seq_len(2), function(n) { function() {n}})
b = lapply(seq_len(2), function(n)  {n})

我们可以看到

a[[1]]() # == 2
b[[1]]   # == 1

我知道 R 使用promise 的对象并在其环境中懒惰地评估一个表达式,但我不明白为什么为每个函数创建的不同环境不包含它们自己的 n 值。

[[1]]
function () 
{
    n
}
<environment: 0x7f9b2416ad18>

[[2]]
function () 
{
    n
}
<environment: 0x7f9b2416ab20>

as.list(environment(a[[1]])) 
$n
[1] 2

as.list(environment(a[[2]]))
$n
[1] 2

是否可以通过 lapply 函数以某种方式修复语义?

lapply
function (X, FUN, ...) 
{
    FUN <- match.fun(FUN)
    if (!is.vector(X) || is.object(X)) 
        X <- as.list(X)
    .Internal(lapply(X, FUN))
}
<bytecode: 0x7f9b25150f18>
<environment: namespace:base>

PS:重新聚焦的问题

编辑:具体来说,是否可以编写一个lapply2函数,该函数通常“强制”参数具有统一的行为,如下所示:

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

2 回答 2

2

我发现这种形式更容易理解:

f=function(n) {function() {n}}
x=1
a=f(x)
x=2
a()
[1] 2

文档的关键部分是

当一个函数被调用时,参数是匹配的,然后每个形式参数都绑定到一个 Promise。为该形式参数给出的表达式和一个指向调用该函数的环境的指针都存储在 Promise 中。

调用之后a=f(x),函数参数n被绑定到一个带有名称x和指向全局环境的指针的promise .GlobalEnv

在您的lapply示例中,function(n) { function() {n}}每次都从全局环境调用匿名函数。这就是为什么列表中的每个元素都a获得相同的值的原因n:它来自全局环境。我看不出如何通过重写 lapply 来改变这种行为。

于 2013-08-01T13:39:17.943 回答
1

不久前我发表了一条评论,这可能是最近版本的情况,R但这里也有一个官方证明,它lapply现在的行为与您的lapply2版本完全一样,取自3.2.0的新闻发布R

  • 高阶函数(例如 apply 函数和 Reduce())现在强制将参数传递给它们应用的函数,以消除惰性求值和闭包中变量捕获之间的不良交互。这解决了 PR#16093。
于 2017-01-24T10:45:39.463 回答