How to check if any arguments were passed via "..." (ellipsis) in R? Is missing(...) valid?
Asked Answered
D

3

18

I'd like to check whether an R function's "..." (ellipsis) parameter has been fed with some values/arguments.

Currently I'm using something like:

test1 <- function(...) {
   if (missing(...)) TRUE
   else FALSE
}

test1()
## [1] TRUE
test1(something)
## [2] FALSE

It works, but ?missing doesn't indicate if that way is proper/valid.

If the above is not correct, what is THE way to do so? Or maybe there are other, faster ways? PS. I need this kind of verification for this issue.

Dhahran answered 31/10, 2014 at 22:48 Comment(1)
#9877771Redcap
R
13

Here's an alternative that will throw an error if you try to pass in a non-existent object.

test2 <- function(...) if(length(list(...))) FALSE else TRUE

test2()
#[1] TRUE
test2(something)
#Error in test2(something) : object 'something' not found
test2(1)
#[1] FALSE
Redcap answered 1/11, 2014 at 0:55 Comment(3)
Sure, but I really wonder also if missing(...) is valid. :) BTW, for the sole purpose of testing if there's something under ..., length(list(...))==0 is a little bit slower. Anyway, thanks!Dhahran
@Dhahran it should be slower because it's forcing evaluation. It's hard to say what's better without knowing why you're checking or what you're doing with that information. Maybe it's better to throw here, maybe it's better to throw later. Presumably, if you find out that there are arguments, you'll do something with them, which will force evaluation and the error. length(list(...)) is also one more function call than missing(...)Redcap
BTW, you said if (length(list(...))==0), and you used if (length(list(...)) > 0) in your benchmark. I think if (length(list(...))) is marginally faster (i.e. the implicity conversion to logical is faster than comparing to a numeric)Redcap
T
5

I think match.call is what you need:

test <- function(...) {match.call(expand.dots = FALSE)}

> test()
test()

> test(x=3,y=2,z=5)
test(... = list(x = 3, y = 2, z = 5))

It will give you every time the values passed in the ellipsis, or it will be blank if you won't pass any.

Hope that helps!

Tagmeme answered 1/11, 2014 at 0:29 Comment(2)
If there were more parameters in the arg list (other than "..."), I should test for any(names(match.call(expand.dots=FALSE)[-1]) == "..."), don't I? :)Dhahran
If you necessarily want it to give you TRUE or FALSE then yeah the above works great. If you don't then the above function works with more parameters other than '...' too. As you already know test <- function(k=7,...) {match.call(expand.dots = FALSE)} for test(x=3,y=2,z=5,k=5) returns test(k = 5, ... = list(x = 3, y = 2, z = 5))Tagmeme
V
0

If it helps anyone I ended up using the following function to get the ellipsis parameters for every function (returns an empty list or a list of arguments):

get.params <- function (...) {
  params <- list()

  if (length(list(...)) && !is.null(...)) 
    params <- unlist(...)

  return(params)
}

for:

f <- function(t, ...) {
 params <- get.params(...)
 print(paste(params))
}
Vintage answered 25/1, 2019 at 15:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.