通过(...)时避免参数重复

时间:2018-10-12 03:34:40

标签: r function arguments

考虑功能

f <- function(x, X) mean(c(x,X))

如何自动(通过操纵f())更改f()的签名,使其可以与lapply()一起使用,即不返回以下明显错误? >

lapply(X=list(1), FUN=f, X=1)
Error in lapply(X = list(1), FUN = f, X = 1) : 
  formal argument "X" matched by multiple actual arguments

到目前为止,我使用的方法是从f()中删除所有参数,将它们分配到一个环境中,然后在该环境中求值f()

integrateArgs <- function (f, args) 
{
    form <- formals(f)
    if (!is.null(form)) 
        for (i in seq_along(form)) assign(names(form)[i], form[[i]])
    if (!is.null(args)) 
        for (i in seq_along(args)) assign(names(args)[i], args[[i]])
    ff <- function() {
    }
    parent.env(environment(ff)) <- parent.env(environment(f))
    body(ff) <- body(f)
    if (any(names(form) == "...")) 
        formals(ff) <- form[names(form) == "..."]
    ff
}
fnew <- integrateArgs(f, list(x=1, X=4))
lapply(list(fnew), function(x) x())
[[1]]
[1] 2.5

但是,如果f()是来自另一个R包的函数,该函数调用已编译的代码,则该方法会导致以下错误。

fnew2 <- integrateArgs(dnorm, list(x=1, mean=4))
lapply(list(fnew2), function(x) x())
Error in x() (from #1) : object 'C_dnorm' not found

有更好的解决方案吗?

1 个答案:

答案 0 :(得分:0)

正如MrFlick的评论中所建议的那样,一种解决方案是

library(purrr)
integrateArgs <- function(f, args){
    do.call(partial, c(list(f), args))
}
fnew2 <- integrateArgs(dnorm, list(x=1, mean=4))
lapply(list(fnew2), function(x) x())
[[1]]
[1] 0.004431848

以下类似方法不需要软件包purrr

integrateArgs <- function(f, args){
    do.call(function(f, ...) {
        eval(call("function", NULL,
                  substitute(f(...))), envir = environment(f))}, 
        c(f = list(f), args))
}
fnew2 <- integrateArgs(dnorm, list(x=1, mean=4))
lapply(list(fnew2), function(x) x())
[[1]]
[1] 0.004431848

optimParallel 版本0.7-4中现在使用了类似的方法,以使用parallel::parLapply()https://cran.r-project.org/package=optimParallel

并行执行功能