使用...参数内联

ste*_*ejb 1 r

我有以下功能

sjbDo <- function(operation, x, statelist, Spos, isFuture = FALSE) {

  # run the operation on x
  xvec <- operation(x);

  # and so on

}
Run Code Online (Sandbox Code Playgroud)

我可以这样称呼它:

A <- sjbDo( function(x) {x}, statelist$A, statelist, 1)
Run Code Online (Sandbox Code Playgroud)

但是,我想修改sjbDo,以便内联函数可以使用其他参数.就像是:

kTheta <- sjbDo( function(x, b) {x^b}, statelist$K, statelist, 1, FALSE, b=theta.k)
Run Code Online (Sandbox Code Playgroud)

我试过了

sjbDo <- function(operation, x, statelist, Spos, isFuture = FALSE, ...) {

  # run the operation on x
  xvec <- operation(x,...);
Run Code Online (Sandbox Code Playgroud)

但这似乎不起作用.我怎样才能让它发挥作用?

Rei*_*son 6

一个更规范的解决方案看起来像:

operation <- function(x, ...) {
    dots <- list(...)
    x^dots[[1]]
}
Run Code Online (Sandbox Code Playgroud)

但如果你足够了解你想要的论点是第一个传递的参数...那么你应该把它作为一个参数.因为你的代码(和我的代码)在这样调用时不起作用,例如:

> operation(1:10, foo = "bar", b = 2)
Error in x^dots[[1]] : non-numeric argument to binary operator
Run Code Online (Sandbox Code Playgroud)

如果你...像我上面那样抓住,那么你可以拉出你想要的参数如果它被命名:

operation <- function(x, ...) {
    dots <- list(...)
    want <- which(names(dots) == "b")
    stopifnot(length(want) > 0)
    b <- dots[[want]]
    x^b
}
Run Code Online (Sandbox Code Playgroud)

其工作方式如下:

> operation(1:10, foo = "bar", b = 2)
 [1]   1   4   9  16  25  36  49  64  81 100
Run Code Online (Sandbox Code Playgroud)

但如果b不是命名参数,仍然会失败:

> operation(1:10, foo = "bar", 2)
Error: length(want) > 0 is not TRUE
Run Code Online (Sandbox Code Playgroud)

因此,您提出的内容可能适用于您提供的一个用例,但这并不是执行您想要执行的操作的更一般策略.我应该operation如果在没有通过额外的参数呢?您的代码假设有其他参数,因此不再是可选的 - 这是您所指出的.如果b提供non,则应该采取一些其他默认值,那么整个事情变得更容易:

operation <- function(x, b = 1) {
    x^b
}

sjbDo <- function(FUN, x, ...) {
    ## function matching
    FUN <- match.fun(FUN)
    # run the operation on x
    xvec <- FUN(x, ...)
    xvec
}
Run Code Online (Sandbox Code Playgroud)

这使:

> sjbDo(operation, 1:10)
 [1]  1  2  3  4  5  6  7  8  9 10
> sjbDo(operation, 1:10, b = 2)
 [1]   1   4   9  16  25  36  49  64  81 100
> sjbDo("operation", 1:10, b = 2)
 [1]   1   4   9  16  25  36  49  64  81 100
Run Code Online (Sandbox Code Playgroud)

后者因使用而起作用match.fun.

上述观点是我不认为你想要operation()一个...参数,因为我不知道这些代码是如何工作的.我认为你想要的是一种编写外部函数调用sjbDo()以获得一些命名参数并将任何其他参数传递给你想要调用的函数的方法sjbDo(),我在这里调用FUN并调用它operation.

换句话说,我认为你想要的是一个wrapper(sjbDo()),可以FUN使用参数调用给定的函数(作为参数提供)x,以及FUN需要的任何其他参数,而不必考虑所有可能的参数FUN将需要?