I got tired of starting my scripts with require(data.table); require(ggplot2)
etc etc. I know that I could do something like lapply(c('data.table', 'ggplot2'), require, character.only=T)
, but it would just return a warning (not an error) for a missing package, plus I wanted my own function require_mult(...)
to keep my scripts cleaner. So I wrote the function:
require_mult <- function(...){
arg_list <- list(...)
if(any(!sapply(arg_list, is.character)) ) stop('require_mult must have character arguments')
check <- tryCatch({pkg_array <- unlist(arg_list)
loaded <- sapply(pkg_array, require, character.only=TRUE, quietly=TRUE)
message('Loaded packages: ',
paste(pkg_array, collapse=', ') ) },
warning = function(w) stop(w), # I want execution to halt if a package is missing
error = function(e) stop(e)
)
}
Which seems to work as desired (e.g., loads for require_mult('data.table','ggplot2')
, errors for require_mult('data.table','ggplotfoo')
), but I would like to make this require_mult(...)
work for character.only=FALSE
. I looked at the definition of require
, which uses
if (!character.only)
package <- as.character(substitute(package))
But I can't figure out how to apply substitute
across an unevaluated expression that's really a comma-delimited list.
I know this application is pretty pointless and academic, but it would enrich my understanding of R expression evaluation if there is in fact a way to write a require_mult
that could be used for require_mult(data.table, ggplot2)
etc.
An explanation of why this can't be done would also be acceptable.
I learned something here today! You can use match.call
to obtain the arguments passed in ...
without evaluating them. (Presumably, you could do this with named arguments...? I need to experiment more on that.) I used this answer to build the very simple function below. As you can see, it breaks when reaching the package that does not exist.
I think you could use this to build further.
library_mult <- function(...) {
args <- match.call(expand.dots = FALSE)$`...`
for(x in args) {
x <- as.character(substitute(x))
library(x,character.only = TRUE)
}
}
> library_mult(MASS,thisisnopack)
Error in library(x, character.only = TRUE) :
there is no package called ‘thisisnopack’