【问题标题】:setting formal arguments of 'foreach' function设置“foreach”函数的形式参数
【发布时间】:2013-06-04 01:26:53
【问题描述】:

我正在尝试设置 foreach 函数的形式参数。我将给出一个使用 .combine 参数的简单示例。

我写了一个通用包装器来改变函数的形式(代码如下)

bind<-function(FUN,args.new) {
    args.all<-formals(FUN)
    args.all[names(args.all) %in% names(args.new)]<-args.new
    FUN.tmp<-FUN
    formals(FUN.tmp)<-args.all
    FUN.tmp
}

所以,我改变了 foreach 函数的形式

library(foreach)    
foreach.bind<-bind(foreach,list('.combine'='rbind'))

当我检查我得到的新形式时(如预期的那样):

> formals(foreach.bind)
$...


$.combine
[1] "rbind"

$.init


$.final
NULL

$.inorder
[1] TRUE

$.multicombine
[1] FALSE

$.maxcombine
if (.multicombine) 100 else 2

$.errorhandling
c("stop", "remove", "pass")

$.packages
NULL

$.export
NULL

$.noexport
NULL

$.verbose
[1] FALSE

> 

但是当我调用 foreach.bind 时,一切都像 .combine 变量没有设置一样!例如,声明:

a<-function(x) c(1,x)

并调用:

> foreach.bind(i=list(1,2,3)) %do% a(i)
[[1]]
[1] 1 1

[[2]]
[1] 1 2

[[3]]
[1] 1 3

> 

正如我所说,.combine 参数没有正式设置。

另一方面,如果我调用它的原始函数:

> foreach(i=list(1,2,3),.combine='rbind') %do% a(i)
         [,1] [,2]
result.1    1    1
result.2    1    2
result.3    1    3
> 

无论如何,谁能解释一下在这种情况下发生了什么?或为我提供“绑定”foreach 函数的其他方法?

【问题讨论】:

  • 我不确定更改形参列表有什么作用,但stackoverflow.com/questions/6547219/… 描述了如何做你想做的事情。
  • 我看到了这篇文章。这正是我的绑定函数所做的。正如史蒂夫所说,这是检查缺失值的 foreach 函数的问题。
  • 我专门指的是 Curry 函数(在接受的答案的最顶部),它 not 做你的 bind 函数所做的事情,而且看起来很远一般情况下更有可能正常工作。

标签: r parallel-processing parallel-foreach


【解决方案1】:

.combine 参数未在 foreach 函数中赋予默认值。相反,foreach 检查是否缺少 .combine 参数。您的代码为.combine 提供了一个默认值,但如果您不为其指定一个值,它仍然会丢失,因此默认的组合行为不会改变。

一种解决方案是创建一个与foreach 具有相同形式参数的包装函数,然后通过操作并评估match.call 返回的调用对象来调用foreach

library(foreach)
foreach.bind <- function() {
    cobj <- match.call()
    cobj[[1]] <- as.name('foreach')
    nms <- names(cobj)
    if (! '.combine' %in%  nms) {
      cobj[[length(cobj) + 1]] <- 'rbind'
      names(cobj) <- c(nms, '.combine')
    }
    eval(cobj)
}
formals(foreach.bind) <- formals(foreach)

这会修改默认的合并行为,同时仍允许您指定自己的合并函数:

> foreach.bind(i=1:3) %do% c(1,i)
         [,1] [,2]
result.1    1    1
result.2    1    2
result.3    1    3
> foreach.bind(i=1:3, .combine='c') %do% c(1,i)
[1] 1 1 1 2 1 3

【讨论】:

  • 感谢您的评论。不幸的是,嵌套函数在我的情况下不起作用。我必须比那更笼统......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-07-30
  • 2012-01-14
  • 2015-10-27
  • 2021-06-30
  • 2012-11-08
  • 1970-01-01
  • 2013-05-21
相关资源
最近更新 更多