本文介绍了您能否更清楚地解释R函数运算符中的惰性求值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我创建如下函数:

what_is_love <- function(f) {
  function(...) {
    cat('f is', f, '\n')
  }
}

并用lapply调用:funs <- lapply(c('love', 'cherry'), what_is_love)

我得到了意外的输出:

> funs[[1]]()
f is cherry
> funs[[2]]()
f is cherry

但是请注意,当您不使用lapply时,情况并非如此:

But note that this is not the case when you do not use lapply:

> f1 <- what_is_love('love')
> f2 <- what_is_love('cherry')
> f1()
f is love
> f2()
f is cherry

有什么作用?

我知道funs <- lapply(c('love', 'cherry'), what_is_love)可以更完整地写出来:

I know that funs <- lapply(c('love', 'cherry'), what_is_love) can be written out more fully:

params <- c('love', 'cherry')
out <- vector('list', length(params))
for (i in seq_along(params)) {
  out[[i]] <- what_is_love(params[[i]])
}
out

但是当我浏览时,我看到这两个功能都有各自的环境:

But when I browse in, I see that both functions have their own environment:

Browse[1]> out[[1]]
function(...) {
    cat('f is', f, '\n')
  }
<environment: 0x109508478>
Browse[1]> out[[2]]
function(...) {
    cat('f is', f, '\n')
  }
<environment: 0x1094ff750>

但是在每种环境中,f是相同的...

But in each of those environments, f is the same...

Browse[1]> environment(out[[1]])$f
[1] "cherry"
Browse[1]> environment(out[[2]])$f
[1] "cherry"

我知道答案是惰性评估",但我正在寻找更多的深度... f如何最终在两种环境中重新分配? f来自哪里?在此示例中,R惰性评估如何工作?

I know the answer is "lazy evaluation", but I'm looking for a bit more depth... how does f end up re-assigned across both environments? Where does f come from? How does R lazy evaluation work under the hood in this example?

-

我知道关于惰性评估和功能的另一个问题,但是它只是说答案是惰性评估",而没有解释惰性评估实际上是如何工作的.我正在寻求更大的深度.

I'm aware of the other question on lazy evaluation and functionals, but it just says the answer is "lazy evaluation" without explaining how the lazy evaluation actually works. I'm seeking greater depth.

推荐答案

执行时

what_is_love <- function(f) {
  function(...) {
    cat('f is', f, '\n')
  }
}

内部函数为f创建了一个外壳,但要注意的是,直到您实际使用传递给函数的变量,该变量仍是一个承诺",并且没有被实际评估.如果要捕获" f的当前值,则需要强制评估promise.您可以为此使用force()函数.

the inner function creates an enclosure for f, but the catch is that until you actually use a variable passed to a function, it remains a "promise" and is not actually evaluated. If you want to "capture" the current value of f, then you need to force the evaluation of the promise; you can use the force() function fo this.

what_is_love <- function(f) {
  force(f)
  function(...) {
    cat('f is', f, '\n')
  }
}
funs <- lapply(c('love', 'cherry'), what_is_love)

funs[[1]]()
# f is love
funs[[2]]()
# f is cherry

在没有force()的情况下,f仍然是列表中两个函数中的一个承诺.直到调用该函数,并且调用该函数时,promise才会被评估为f的最后一个已知值,即樱桃".

Without force(), f remains a promise inside both of the functions in your list. It is not evaluated until you call the function, and when you call the function that promise is evaluated to the last known value for f which is "cherry."

正如@MartinMorgran指出的那样,此行为在R 3.2.0中已更改.从发行说明

As @MartinMorgran pointed out, this behavior has changed in R 3.2.0. From the release notes

这篇关于您能否更清楚地解释R函数运算符中的惰性求值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-26 05:52