views:

70

answers:

3

If I want to know what is stored in a ... argument within an R function, I can simply convert it to be a list, like so

foo <- function(...)
{
  dots <- list(...)
  print(dots)
}

foo(x = 1, 2, "three")
#$x
#[1] 1
#
#[[2]]
#[1] 2
#
#[[3]]
#[1] "three"

What I can't figure out is how to evaluate ... in the calling function. In this next example I want the contents of baz to return the ... argument to bar.

bar <- function(...)
{
  baz()
}

baz <- function()
{ 
  # What should dots be assigned as?
  # I tried                                           
  # dots <- get("...", envir = parent.frame())
  # and variations of
  # dots <- eval(list(...), envir = parent.frame())
  print(dots)
}

bar(x = 1, 2, "three")

get("...", envir = parent.frame()) returns <...>, which looks promising, but I can't figure out how to extract anything useful from it.

eval(list(...), envir = parent.frame()) throws an error, claiming that ... is used incorrectly.

How can I retrieve the ... from bar?

+1  A: 

This should work:

bar <- function(...)
{
  baz(...=...)
}

baz <- function(...)
{ 
  print(list(...))
}

bar(x = 1, 2, "three")

Just assign it in the subfunction.

Alternatively, you can assign the ellipsis as a list in the parent function:

bar <- function(...)
{
  bar.x <- list(...)
  baz()
}

baz <- function()
{ 
  dots <- get("bar.x", envir = parent.frame())
  print(dots)
}

bar(x = 1, 2, "three")

This is the same idea, but I wouldn't suggest it because you're overwriting the ellipsis:

bar <- function(...)
{
  ... <- list(...)
  baz()
}

baz <- function()
{ 
  dots <- get("...", envir = parent.frame())
  print(dots)
}

bar(x = 1, 2, "three")
Shane
@Shane: Thanks, but what if I can't/don't want to modify `baz`? Is evaluating `...` in a different environment possible?
Richie Cotton
See my second solution? I'm not sure about that <...> object; it's class is "..." and it clearly isn't the same as the original ellipsis.
Shane
+2  A: 

Figured it out. I needed a combination of eval and substitute. baz should be defined as

baz <- function()
{ 
  dots <- eval(substitute(list(...), env = parent.frame()))
  print(dots)
}
Richie Cotton
+1 This is an interesting example. If you have a chance, it would be nice if you could update this with an explanation for *why* this might be necessary for the ellipsis, but not for other variables?
Shane
@Shane: A good question. I'm going to dig around further, but this is rapidly getting into brain-melting territory. To be continued...
Richie Cotton
A: 

In a word: don't. Trying to redefine R's scoping rules is only likely to end up in heartache and pain.

hadley