Dav*_*vid 9 loops functional-programming r
在函数式编程的介绍中,作者Hadley Wickham创建了以下函数工厂:
power <- function(exponent) {
function(x) {
x ^ exponent
}
}
Run Code Online (Sandbox Code Playgroud)
然后他展示了如何使用此函数来定义其他函数,例如
square <- power(2)
cube <- power(3)
Run Code Online (Sandbox Code Playgroud)
现在假设我想通过以下循环同时创建这些函数:
ftns <- lapply(2:3, power)
Run Code Online (Sandbox Code Playgroud)
这似乎不起作用,因为3被分配给列表的所有条目的指数:
as.list(environment(ftns[[1]]))
$exponent
[1] 3
Run Code Online (Sandbox Code Playgroud)
有人可以帮我理解这段代码有什么问题吗?
谢谢!
你所看到的是R使用承诺实施懒惰论证评估的结果.请参阅Promise对象.
问题是在power()函数exponent中永远不会计算参数,这意味着永远不会调用基础的promise(至少在评估生成的函数之前).
您可以强制承诺如下评估:
power <- function(exponent) { exponent; function(x) x^exponent; };
ftns <- lapply(2:3,power);
sapply(ftns,function(ftn) environment(ftn)$exponent);
## [1] 2 3
Run Code Online (Sandbox Code Playgroud)
如果没有exponent;声明强制评估承诺,我们会看到问题:
power <- function(exponent) { function(x) x^exponent; };
ftns <- lapply(2:3,power);
sapply(ftns,function(ftn) environment(ftn)$exponent);
## [1] 3 3
Run Code Online (Sandbox Code Playgroud)
啊哈!R changelog显示此行为在3.2.0中已更改:
*诸如apply函数和Reduce()之类的高阶函数现在强制对它们应用的函数进行参数化,以消除惰性求值和闭包中变量捕获之间的不良交互.这解决了PR#16093.
它被归类为新功能.