Home > front end >  How can I create a list of n user input objects (i.e. `...` ) in R which handles objects which do no
How can I create a list of n user input objects (i.e. `...` ) in R which handles objects which do no

Time:11-06

I'm trying to write a function that accepts any number of objects and returns them in a list. It should display warnings for objects which do not exist but return a list of those objects which do exist.

Here is an example.

a <-  data.frame(A = 1:2)
b <- 4
c <- list(5,4,3)


f <- function(...) {
    
    list(...)
}
# Function returns a list(a,b,c)
f(a,b,c)
# Function errors as d does not exist
# Error in test(a, b, c, d): object 'd' not found
f(a, b, c, d)

I want to modify f, so that the function returns list(a,b,c) for f(a, b, c, d) plus a warning saying d doesn't exist.

I don't know when R tries to find d but I was thinking something along the lines of checking which objects exist and subsetting the list to just those objects which do.

list_in <- list(...)
list_in[[(sapply(..., exists))]]

but the error appears to happen before R even begins trying to run the function code?

CodePudding user response:

I would advise against using a function like this. It is not good practice to have a function that doesn't throw an error when called on a non-existent variable. It is not idiomatic R, and can easily cause major problems through simple typos.

This version will also not work when passing numbers or characters or expressions directly, such as f(1 1, "hello", a), though it could be made to do so with a bit of work.

f <- function(...) {
  all_vars <- as.list(match.call())[-1]
  all_names <- sapply(all_vars, is.name)
  if(any(!all_names)) stop("Only named objects can be passed to function f")
  var_names <- sapply(all_vars, as.character)
  var_exists <- sapply(var_names, exists)
  if(any(!var_exists))
  {
    warning("Variables ", paste(var_names[!var_exists], collapse = ", "),
            " were not found in the search path.")
  }
  
  lapply(var_names[var_exists], get, env = parent.frame())
}

So, for example.

a <-  data.frame(A = 1:2)
b <- 4
c <- list(5,4,3)

f(a, b, c, d, e)
#> [[1]]
#>   A
#> 1 1
#> 2 2
#> 
#> [[2]]
#> [1] 4
#> 
#> [[3]]
#> [[3]][[1]]
#> [1] 5
#> 
#> [[3]][[2]]
#> [1] 4
#> 
#> [[3]][[3]]
#> [1] 3

#> Warning message:
#> In f(a, b, c, d, e) : Variables d, e were not found in the search path.
  • Related