Search code examples
rrequiresapply

R function `require` does not work as expected in `sapply`


I want to check if a bunch of packages are correctly installed (to make a dockerfile crash and not silently continue).

I tried a sapply on a list of package names, and this is what happens. Note that:

  • 'not_available' is not installed :)
  • 'testthat' is installed.
# to show the invisible output:
> show <- function(x) {cat(x, '\n')}

> show(require('not_available'))
Loading required package: not_available
FALSE
Warning message:
In library(package, lib.loc = lib.loc, character.only = TRUE, logical.return = TRUE,  :
  there is no package called ‘not_available’

So far so good, precisely as expected.

> show(require('testthat'))
TRUE

perfect...

> sapply(c('not_available', 'testthat'), require, warn.conflicts = FALSE, quietly = TRUE)
not_available      testthat 
        FALSE         FALSE 
Warning messages:
1: In if (!loaded) { :
  the condition has length > 1 and only the first element will be used
2: In if (!loaded) { :
  the condition has length > 1 and only the first element will be used

Wuuut...

why does it warn us? And why is the output incorrect?

> sapply(c('not_available', 'testthat'), function(x) {x})
  not_available        testthat 
"not_available"      "testthat" 

Oke, so sapply is not betraying me...

> sapply(c('not_available', 'testthat'), function(pkg) {require(pkg, warn.conflicts = FALSE, quietly = TRUE)})
not_available      testthat 
        FALSE         FALSE 

Eeeh, now the warning is gone, but the answer.... still wrong... why?

Any clue? Expected behaviour would be a returned value with [FALSE TRUE] (relating to 'not_available' and 'testthat').


Solution

  • Alright, it is due to the special 'library' and 'require' behaviour to also work with unquoted values. So the following will demonstrate the failure:

    pkgs <- 'testthat'
    require(pkgs)
    Loading required package: pkgs
    Warning message:
    In library(package, lib.loc = lib.loc, character.only = TRUE, logical.return = TRUE,  :
      there is no package called ‘pkgs’
    

    The solution is to provide 'character.only'

    sapply(c('not_available', 'testthat'), require, character.only = TRUE)
    not_available      testthat 
            FALSE          TRUE
    

    works just fine.