'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 1:[1]

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.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1