使用R中的循环创建函数列表

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)

有人可以帮我理解这段代码有什么问题吗?

谢谢!

bgo*_*dst 6

你所看到的是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.

它被归类为新功能.