【问题标题】:Lazy evaluation and promise data structure惰性求值和promise数据结构
【发布时间】:2021-04-25 15:27:59
【问题描述】:

自从我第一次在 Advanced R 上阅读 Promise 以来,我一直在努力解决它的应用问题。有人提到,Promise 是一种支持惰性求值的数据结构。惰性求值的概念非常清楚,因为函数参数仅在被访问时才被求值。但是,在某些示例中,我只是无法发现 Promise 的存在以及如何/在何处评估它。考虑一下 Advanced R 中的以下示例:

y <- 10
h02 <- function(x) {
  y <- 100
  x + 1
}

h02(y)
[1] 11

它返回 11 而不是 101,显然,当我们将全局环境中已经存在的 y 之类的变量分配给 x 时,它会在函数外部绑定和评估。 所以我想知道一个承诺总是涉及某种赋值,或者每个表达式都可能是一个承诺,以及我们如何检测它们的存在。 提到它们是在函数的调用环境中评估的。所以第二个问题是他们的评估环境与普通参数不同,因为用户定义的参数是在函数之外评估的。

还有一个例子我不明白为什么它涉及惰性评估,我们只看到一次Calculating...

double <- function(x) {
message("Calculating...")
x * 2
}
h03 <- function(x) {
c(x, x)
}
h03(double(20))
Calculating...
[1] 40 40

如果我在这里听起来有点困惑,我很抱歉,我明白了这一点,但它从来没有完全深入,我想寻求一点解释,对此我非常感激。

非常感谢您

【问题讨论】:

  • 我不确定我是否明白你在这里问什么。 Promise 确实知道它们是在什么环境中创建并在那里进行评估的。没有基本的 R 方法来检查某个东西是否是一个承诺,因为一旦你看到它,它就会被评估并且不再是一个承诺。一个promise 永远不会被多次评估。 Promise 更多的是实现细节,而不是你直接使用的东西。
  • 感谢您的回复。我理解,只是有时我无法解释它们以及它们是如何发生的,例如我想知道为什么我的第二个示例是一个承诺,因此只评估了一次。

标签: r promise lazy-evaluation


【解决方案1】:

当在函数中创建 h02 中的 y 等对象时,它会在该函数的本地执行框架/环境中创建(每次运行函数时都会创建一个新框架)。创建的对象不同于任何其他环境中的同名对象。

关于h03,一旦一个promise被强制执行,即被评估,它的值被存储在promise的value组件中并且它的evaled组件被设置为TRUE,这样在进一步访问时它就不必再次被评估。

函数的参数是承诺,但通常不是其他对象。使用 pryr 检查对象。

library(pryr)

f <- function(x) { 
  z <- 1

  cat("is_promise(z):", is_promise(z), "\n")

  cat("is_promise(x):", is_promise(x), "\n")
  cat("before forcing - promise_info(x):\n")
  print(promise_info(x))

  force(x)
  cat("after forcing - promise_info(x):\n")
  print(promise_info(x))

  delayedAssign("w", 3)
  cat("is_promise(w):", is_promise(w), "\n")

  invisible()
}
a <- 3
f(a)

给予:

is_promise(z): FALSE 
is_promise(x): TRUE 
before forcing - promise_info(x):
$code
a

$env
<environment: R_GlobalEnv>

$evaled
[1] FALSE

$value
NULL

after forcing - promise_info(x):
$code
a

$env
NULL

$evaled
[1] TRUE

$value
[1] 3

is_promise(w): TRUE

【讨论】:

  • 非常感谢您的详尽解释。我真的很感谢你的时间。我只有两个非常简单的问题。在h02(y) 的情况下,可以肯定地说,作为一般规则,由于y 是用户定义的参数,它在函数的调用环境中进行评估,在这种情况下是全局环境,所以这就是为什么即使我们在执行框架中有一个y,该函数在调用环境中使用那个来进行计算?
  • 是的,如果你说从参数创建的承诺总是在调用者的环境中评估。
  • 非常感谢您抽出宝贵的时间,格洛腾迪克先生。我希望你能考虑我的问题,我现在非常感激。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-23
  • 1970-01-01
  • 2017-04-26
  • 1970-01-01
相关资源
最近更新 更多