Updated: 2022-10-09

Just to remind me how I could use ellipsis or the three dots ... in my coding. There are three scenarios I find it useful:

Function wrapper

When creating a function wrapper and instead of providing all the arguments to be send further, you could just use ... ellipsis. For example:

  get_mean <- function(x, print = TRUE){

    x1 <- mean(x)
    if (print){
      print(x1)
    }else{
      print("Nothing")
    }
  }

  get_mean(1:10)

  show_mean <- function(...){
    get_mean(...)
  }

  show_mean(x = 1:10, print = F)

  do.call(show_mean, list(x = 1:20))
  do.call(show_it, list(x = 1:20, print = FALSE))

In show_mean the arguments given will be sent further to get_mean without the need to define explicitly in show_mean function.

Get values

When you want to provide certain values to a specific use or send to global value.

  go_global <- function(...) {
    args <- list(...)
    paste(args)

    for(i in 1:length(args)) {
      assign(x = names(args)[i], value = args[[i]], envir = .GlobalEnv)
    }

  }

  go_global("Hello", "World")

This is of course not advisable sending value to global environment but here is just to show how you could manipulate the value as you wish. The values in ellipsis should be captured as a list.

You could also capture the names of the list by names(list(...)).

Input arguments

Two methods that I use to get input from ellipsis:

Method I

To use it as input argument without quote. Use eval(substitute(alist(...))) and deparse as shown below:

make_filegroups <- function(...){

  fgp <- tryCatch({
    unlist(list(...))
  },
  error = function(err){err}
  )

  if (is(fgp, "error")){
    dots <- eval(substitute(alist(...)))
    fgp <- sapply(as.list(dots), deparse)
  }

  for (i in fgp){
    i <- trimws(i)
    make_file(i, save = TRUE)
  }
}

make_filegroups(GROUP1, GROUP2)

For the go_global example, can be written as:

go_global <- function(...){
  dots <- eval(substitute(alist(...)))
  sapply(as.list(dots), deparse)
}

go_global(Hello, World)

Method II

Use match.call function. Arg char here is just to make it flexible if you want to use vector but isn’t necessary.

go_global <- function(..., char){
  if (missing(char)){
    dots <- as.character(match.call(expand.dots = FALSE)[[2]])
  } else {
    dots <- char
  }

  return(dots)
}

go_global(hello, world)

h <- c("hello", "world")
go_global(char = h)
comments powered by Disqus