使用R中的循环创建函数列表 [英] Creating a list of functions using a loop in R

查看:111
本文介绍了使用R中的循环创建函数列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

函数式编程入门中,作者Hadley Wickham创建了以下函数工厂:

  power<  -  function(exponent){
function(x){
x ^ exponent


$ / code>

然后他展示了如何使用这个函数来定义其他函数,例如

  square < -  power(2)
cube < - power(3)

现在假设我想通过以下循环同时创建这些函数:

  ftns < -  lapply(2:3,power)

这似乎并不奏效,因为3被分配给列表中所有条目的指数:

  as.list(environment(ftns [[1]]))

$ exponent
[1] 3

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



谢谢!

解决方案

你看到的是R使用 promise 实施懒惰的论证评估。请参阅承诺对象



问题在于 power()函数中指数参数永远不会被评估,这意味着潜在的承诺永远不会被调用(至少直到生成的函数被评估)。

你可以强制承诺被评估为像这个:

  power<  -  function(exponent){exponent;函数(x)x ^指数; }; 
ftns < - lapply(2:3,power);
sapply(ftns,function(ftn)environment(ftn)$ exponent);
## [1] 2 3

没有指数; 声明强制评估承诺,我们看到这个问题:
$ b $ pre $ lt; code> power< - function指数){函数(x)x ^指数; };
ftns < - lapply(2:3,power);
sapply(ftns,function(ftn)environment(ftn)$ exponent);
## [1] 3 3






啊哈! R 更新日志显示此行为在3.2.0中已更改:


*如apply函数和Reduce()
等高阶函数现在强制将参数应用到
消除懒惰评估与闭包中
变量捕获之间的不良交互作用。这解决了PR#16093。

它被分类为新功能。


In this introduction to functional programming, the author Hadley Wickham creates the following function factory:

power <- function(exponent) {
  function(x) {
    x ^ exponent
 }
}

He then shows how this function can be used to define other functions, such as

square <- power(2)
cube <- power(3)

Now suppose I wanted to create these functions simultaneously via the following loop:

ftns <- lapply(2:3, power)

This doesn't seem to work, as 3 gets assigned to the exponent for all entries of the list:

as.list(environment(ftns[[1]]))

$exponent
[1] 3

Can someone please help me understand what's wrong with this code?

Thanks!

解决方案

What you're seeing is a consequence of R's use of promises to implement lazy argument evaluation. See Promise objects.

The problem is that in the power() function the exponent argument is never evaluated, meaning the underlying promise is never called (at least not until the generated function is evaluated).

You can force the promise to be evaluated like this:

power <- function(exponent) { exponent; function(x) x^exponent; };
ftns <- lapply(2:3,power);
sapply(ftns,function(ftn) environment(ftn)$exponent);
## [1] 2 3

Without the exponent; statement to force evaluation of the promise, we see the issue:

power <- function(exponent) { function(x) x^exponent; };
ftns <- lapply(2:3,power);
sapply(ftns,function(ftn) environment(ftn)$exponent);
## [1] 3 3


Aha! The R changelog shows that this behavior was changed in 3.2.0:

* Higher order functions such as the apply functions and Reduce() now force arguments to the functions they apply in order to eliminate undesirable interactions between lazy evaluation and variable capture in closures. This resolves PR#16093.

It's classified as a new feature.

这篇关于使用R中的循环创建函数列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆