установка формальных аргументов функции foreach

Я пытаюсь установить формальные аргументы функции 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?


person Marcelo Sardelich    schedule 04.06.2013    source источник
comment
Я не уверен, что меняет список формальных параметров, но stackoverflow.com/questions/6547219/ описывает, как сделать то, что вы пытались сделать.   -  person zwol    schedule 04.06.2013
comment
Я видел этот пост. Это именно то, что делает моя функция привязки. Как сказал Стив, это проблема с функцией foreach, которая проверяет отсутствующие значения.   -  person Marcelo Sardelich    schedule 04.06.2013
comment
Я имел в виду конкретно функцию Curry (в самом верху принятого ответа), которая не выполняет то, что делает ваша функция привязки, и которая, похоже, с большей вероятностью будет работать правильно в целом.   -  person zwol    schedule 04.06.2013


Ответы (1)


Аргументу .combine не присвоено значение по умолчанию в функции foreach. Вместо этого foreach проверяет, отсутствует ли аргумент .combine. Ваш код предоставляет значение по умолчанию для .combine, но если вы не укажете для него значение, оно все равно отсутствует, и поэтому поведение объединения по умолчанию не изменится.

Одно из решений - создать функцию-оболочку, которая имеет те же формальные аргументы, что и foreach, а затем вызывает foreach, манипулируя и затем оценивая объект вызова, возвращаемый match.call:

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
person Steve Weston    schedule 04.06.2013
comment
Спасибо за ваш комментарий. К сожалению, в моем случае вложенная функция не работает. Я должен быть более общим, чем это ... - person Marcelo Sardelich; 04.06.2013