lapply/R的承诺

nic*_*las 5 binding r higher-order-functions

我不确定R中的承诺是做什么的

如果一个人跑

a = lapply(seq_len(2), function(n) { function() {n}})
b = lapply(seq_len(2), function(n)  {n})
Run Code Online (Sandbox Code Playgroud)

我们可以看到

a[[1]]() # == 2
b[[1]]   # == 1
Run Code Online (Sandbox Code Playgroud)

我理解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
Run Code Online (Sandbox Code Playgroud)

是否有可能以某种方式通过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>
Run Code Online (Sandbox Code Playgroud)

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

Ale*_*ysz 2

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

f=function(n) {function() {n}}
x=1
a=f(x)
x=2
a()
[1] 2
Run Code Online (Sandbox Code Playgroud)

文档的关键部分是

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

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

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