用输入作为非字符列表加载多个包的函数

时间:2015-12-18 15:10:19

标签: r ellipsis expression-evaluation

我已经厌倦了用require(data.table); require(ggplot2)等开始我的脚本。我知道我可以做lapply(c('data.table', 'ggplot2'), require, character.only=T)之类的事情,但它只会为丢失的包返回警告(而不是错误),加上我想要自己的函数require_mult(...)来保持我的脚本清洁。所以我写了这个函数:

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)
                       )
}

这似乎可以按预期工作(例如,require_mult('data.table','ggplot2')的加载,require_mult('data.table','ggplotfoo')的错误),但我希望此require_mult(...)适用于character.only=FALSE。我查看了使用

require的定义
if (!character.only) 
        package <- as.character(substitute(package))

但我无法弄清楚如何将substitute应用于未经评估的表达式,而该表达式实际上是以逗号分隔的列表。

我知道这个应用程序是毫无意义和学术性的,但是如果实际上有一种编写可用于require_mult等的require_mult(data.table, ggplot2)的方法,它将丰富我对R表达式评估的理解。

解释为什么不能这样做也是可以接受的。

1 个答案:

答案 0 :(得分:1)

我今天在这里学到了一些东西!您可以使用match.call来获取...中传递的参数,而无需对其进行评估。 (据推测,你可以用命名参数来做这个......?我需要对此进行更多实验。)我使用this answer来构建下面非常简单的函数。如您所见,它在到达不存在的包时会中断。

我认为你可以用它来进一步构建。

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’