了解 R 中的惰性求值
Understanding lazy evaluation in R
我正在尝试了解 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
调用,即使它的结果没有被使用。
有人可以确切地解释一下这是如何工作的,或者指出详细解释的方向吗?
类似问题:
正如您已经发现的那样,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
在创建时不会被求值,delayedAssign()
只会返回求值 x
的承诺,并且仅当我们实际需要 [=15= 的值时],在这种情况下,为了确定其长度,x
被评估。
表达式是放在函数中还是在全局环境中执行都没有关系,所以你在示例中将表达式封装在函数中并没有真正添加任何东西,这就是为什么我排除它。但如果你想确定,试试:
a.f <- function(z) { delayedAssign("x", sample(1E8)); return(z+1) }
system.time(a.f(0))
user system elapsed
0 0 0
我正在尝试了解 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
调用,即使它的结果没有被使用。
有人可以确切地解释一下这是如何工作的,或者指出详细解释的方向吗?
类似问题:
正如您已经发现的那样,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
在创建时不会被求值,delayedAssign()
只会返回求值 x
的承诺,并且仅当我们实际需要 [=15= 的值时],在这种情况下,为了确定其长度,x
被评估。
表达式是放在函数中还是在全局环境中执行都没有关系,所以你在示例中将表达式封装在函数中并没有真正添加任何东西,这就是为什么我排除它。但如果你想确定,试试:
a.f <- function(z) { delayedAssign("x", sample(1E8)); return(z+1) }
system.time(a.f(0))
user system elapsed
0 0 0