Search code examples
rfunctionellipsis

Why does R ellipsis (...) match more arguments when using nested functions?


I would like to understand why the ... argument matches the extra argument when nesting f() within g().

Say that f() is this function:

f <- function(..., extra = NULL) {
    . <- list(...)
    print(.)
}

The output is, as expected, what is contained in the ... argument:

f("a", "b", "c", extra = "123")

# [[1]]
# [1] "a"

# [[2]]
# [1] "b"

# [[3]]
# [1] "c"

However, when using it within another function, say g():

g <- function(..., extra = NULL) {
    f(..., extra)
}

The ... also captures the extra argument:

g("a", "b", "c", extra = "123")

# [[1]]
# [1] "a"

# [[2]]
# [1] "b"

# [[3]]
# [1] "c"

# [[4]]
# [1] "123"

My question is twofold: (1) why is this the case and (2) how to correctly handle this?


Solution

  • In f() you define and set an argument called extra, that is never used, thus it doesnt appear anywhere. The f(..., extra) in g() captures all the arguments in g and assigns them to ... in f(). The extra in g(..., extra) has nothing to do with the extra in f(..., extra = NULL). They have the same names but live in different environments - the environments of g()and f() respectively. To achieve the same behaviour assign the g()'s extra to f()'s extra in the function call:

    g1 <- function(..., extra = NULL) {
        f(..., extra = extra)
    }
    > g1("a", "b", "c", extra = NULL)
    [[1]]
    [1] "a"
    
    [[2]]
    [1] "b"
    
    [[3]]
    [1] "c"
    
    >