【问题标题】:Promises in lapply / Rlapply / R中的承诺
【发布时间】:2013-07-06 00:38:25
【问题描述】:

我不确定承诺在 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's object 并在其环境中懒惰地评估表达式,但我不明白为什么为每个函数创建的不同 环境 不包含它们自己的 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) } )

【问题讨论】:

  • 我有点困惑。是不是因为每个函数的环境只包含承诺,而不是价值,直到需要它才被评估,正如您在上一个问题中所解释的那样?
  • 现在您将闭包与值进行比较。我会说这就像苹果和橘子,但是 improbable.com/airchives/paperair/volume1/v1i3/… 。所以我只会说“不要这样做”。
  • 是的,问题不在于承诺本身,只要环境得到充分跟踪。
  • 我想发布一个更新 - R 中的情况似乎发生了变化,从你的问题开始的代码 sn-ps 现在确实返回了相同的结果。我记得在 Hadley Wickham 的 Advanced R 书中看到了同样的情况,其中代码 sn-p 警告有关承诺的危险实际上正在产生其他东西。据我了解 - lapply 现在可能会强制其 FUN arg 类似于您的 lapply2 建议。

标签: r binding higher-order-functions


【解决方案1】:

我觉得这种形式更容易理解:

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

文档的关键部分是

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

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

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

【讨论】:

  • 可能就是这样。但这对于用其他语言实现闭包似乎很奇怪。根据定义,当给定相同的参数时,函数应该始终返回相同的结果。
【解决方案2】:

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

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

【讨论】:

  • 这太棒了!谢谢你提到它。那么它将更像常规的函数式语言,在关闭后保留词法范围。大获成功
猜你喜欢
  • 2018-06-23
  • 1970-01-01
  • 2015-10-06
  • 2023-03-26
  • 2013-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多