将参数传递给 R 中的调用函数时出现问题

Problem passing arguments to called functions in R

上下文: 我正在尝试使用调用其他函数 (callees).每个被调用函数都使用一组参数,这些参数可以因函数而异。

问题: 看来我必须在调用函数中使用参数才能将它们传递给被调用函数(参见下面示例中的 fun_d ).

问题:如何使用省略号来避免在调用函数中使用显式参数?

Using ellipsis in nested functions and 好像没有回答这个(或者我没理解正确)

代表:

# fun_a and fun_b have the same set of argument but do not do the same things with them
fun_a <- function(x, y, ...){x+y}
fun_b <- function(x, y, ...){x-y}

# I would like to use fun_a and fun_b in another function (fun_c) AND, have the possibility to 
# give different values for each argument of fun_a and fun_b (ex: y1 and y2)

# I thought I could use the ellipsis like in fun_c:
fun_c <- function(...){
  fa <- fun_a(x = x, y = y1)
  fb <- fun_b(x = x, y = y2)
  paste(fa, fb)
}
# fun_d works but I you like to understand why func_c does not
fun_d <- function(x, y1, y2, ...){
  fa <- fun_a(x = x, y = y1)
  fb <- fun_b(x = x, y = y2)
  paste(fa, fb)
}

mapply(FUN = fun_c, x = c(1, 2, 3), y1 = c(1, 2, 3), y2 = c(0, 0, 0)) # not working, it says "x" is missing (and I suppose "y" too)
#> Error in fun_a(x = x, y = y1): object 'x' not found
mapply(FUN = fun_d, x = c(1, 2, 3), y1 = c(1, 2, 3), y2 = c(0, 0, 0)) # working
#> [1] "2 1" "4 2" "6 3"

reprex package (v2.0.0)

于 2021-06-23 创建

根据我的经验,通常可以通过将参数拉入命名空间来解决这个问题(未经测试):

fun_c <- function(...){
  with(list(...), {
    fa <- fun_a(x = x, y = y1)
    fb <- fun_b(x = x, y = y2)
    paste(fa, fb)
  })
}

... 允许函数的调用者将任意参数传递给函数。

但它不会在函数内部创建相应的参数变量。如果你想在函数中使用通过 ... 传递的参数,你有这些选择:

  1. 您可以按原样传递 ...。例如:

    print_two_vectors = function (x, y, ...) {
        print(x, ...)
        print(y, ...)
    }
    

    这可用于将任意参数传递给常规 print 函数:

    print_two_vectors(pi, exp(1), digits = 2L)
    
    [1] 3.1
    [1] 2.7
    

    这个应该...最常使用的。对于大多数其他用途,您应该改为接受常规参数。

  2. 您可以通过 ..1..2 等顺序访问它们。...elt(n) 为您提供 n第一个论点。要找出 传递了多少 个参数,您可以使用 ...length():

    example = function (...) {
        message('Got ', ...length(), ' arguments. The first two are: ', toString(c(..1, ..2)))
        message('The last one is: ', toString(...elt(...length())))
    }
    

    输出结果如下:

    example(1, 2, 3, 4)
    
    Got 4 arguments. The first two are: 1, 2
    The last one is: 4
    
  3. 您可以将它们解压缩到一个列表中。严格来说,这与 (1) 相同,即您只是将 ... 传递给 list 函数。这允许您通过名称 访问元素 ,因为列表可以命名为:

    add_xy = function (...) {
        args = list(...)
        args$x + args$y
    }
    
    add_xy(x = 1, y = 2)
    
    [1] 3
    

    ……好吧,那个例子有点没用。但是您可以使用相同的方法来解决您的问题。

  4. 您可以在未计算的上下文中访问 ... 的值。这是一个高级主题。它在 R 的“常规”使用中并不经常有用,但在 using non-standard evaluation for metaprogramming.

    时它变得强大
    add_xy2 = function (...) {
       call = match.call()
       eval.parent(call$x) + eval.parent(call$y)
    }
    
    add_xy2(x = 1, y = 2)
    
    [1] 3