Search code examples
rellipsis

strange bug using the three dot "..." argument


I need help figuring out what is going on here.

g <- function(x, y=NULL, z=NULL) invisible(NULL)

h <- function(...) {
    args <- as.list(match.call(g))[-1]
    print(args)
    ## lapply(args, eval)
}

f <- function(...) {
    h(...)
}

Function h() prints a named list of unevaluated arguments and then tries to evaluate the arguments.

See what happens when f is called with z=3 and z=-3.

> f(1, z=3)
$x
[1] 1

$z
[1] 3

> f(1, z=-3)
$x
[1] 1

$z
..2

What is this ..2? Notice that h(1, z=-3) produces a different output:

> h(1, z=-3)
$x
[1] 1

$z
-3

Solution

  • The second question is easy. You have a function that creates a side-effect of printing from the inside of a function as the last called function. The print function returns its argument as a value so when the function exits the read-eval-print behavior of the console displays it again.

    The first question delves into the inner workings a bit more. The items in the ellipsis get temporary names: ..1, ..2, ..3, etc. When using the minus sign in front of the 2 you are actually applying a unary operator to change its value. You get exactly the same result with log(2) as the second argument:

    > f(1,log(2))
    $x
    [1] 1
    
    $y
    ..2
    

    I think the reason that the ..2 doesn't appear when the second argument to f is atomic is that a different evaluation process (or no evaluation) process is needed. The same behavior occurs with a character object.

    > f(1,"a")
    $x
    [1] 1
    
    $y
    [1] "a"