了解R中的延迟评估

时间:2017-03-09 08:25:22

标签: r function haskell lazy-evaluation

我试图理解R中的懒惰评估是如何运作的。它是否仅适用于函数参数的评估?因为我理解,例如

f <- function(x = x, y = x*2) {
  c(x, y)
}

f(2)
[1] 2 4

但在其他语言中,例如Haskell,惰性求值意味着函数调用仅在实际使用时才会被评估。所以我希望这样的东西能在瞬间运行:

g <- function(x) {
  y <- sample(1:100000000)
  return(x)
}

g(4)

但它清楚地评估sample调用,即使其结果未被使用。

有人可以确切地解释这是如何运作的,还是指向我详细解释的方向?

类似的问题:

Question with similar wording, but different problem

1 个答案:

答案 0 :(得分:7)

正如您已经发现的那样,R在一般意义上不使用惰性评估。但是R确实通过函数delayedAssign()提供了这个功能,如下所示:

> system.time(y <- sample(1E8))
   user  system elapsed 
  7.636   0.128   7.766 
> system.time(length(y))
   user  system elapsed 
      0       0       0 
system.time(delayedAssign("x", sample(1E8)))
   user  system elapsed 
  0.000   0.000   0.001 
> system.time(length(x))
   user  system elapsed 
  7.680   0.096   7.777 

如您所见,y会立即进行评估,因此确定y的长度根本不需要时间。另一方面,x在创建时未进行评估,x仅返回评估delayedAssign()的承诺,且仅当我们确实需要值x时才会},在这种情况下确定其长度,x进行评估。

表达式是放在函数中还是在全局环境中执行并不重要,因此在您的示例中对函数执行的表达式封装并没有真正添加任何内容,这就是我排除它的原因。但如果你想确定,请尝试:

a.f <- function(z) { delayedAssign("x", sample(1E8)); return(z+1) }
system.time(a.f(0))
   user  system elapsed 
      0       0       0