1

I'm just testing loading different packages, and I wrote a function that I thought would let me add and remove packages as needed. For example, if I wanted to load spatstat:

packagedelivery<-function(fry,leela){
  if(fry == TRUE){
    
    
    library(leela)
} else{
  detach(leela,unload=TRUE)
}
}

packagedelivery(TRUE,"spatstat")

R kicks up an error, stating:

 Error in library(leela) : there is no package called ‘leela’ 

What steps am I missing here?

Many thanks.

OpenSauce
  • 354
  • 2
  • 14
  • 3
    Non-standard evaluation. Use 'require' with 'character.only = TRUE'. – Roland May 28 '21 at 16:33
  • As suspected, functions for TRUE but not FALSE. FALSE condition gives ````Error in detach(leela, unload=TRUE) : invalid 'name' argument"```` – OpenSauce May 28 '21 at 16:57
  • the `detach` function should also have a `character.only` argument as well. – Justin Landis May 28 '21 at 17:30
  • 1
    Only use `require` (with or without `character.only` if you're going to check its return value, otherwise it's the wrong tool. `library(..., character.only=)` exists. One can use `detach(paste0("package:", leela), unload=TRUE)`, but that will only work if no other still-loaded packages depend on it. (This problem is also present for `unloadNamespace`, so is not unique to `detach`.) – r2evans May 28 '21 at 19:28
  • By adding a grepl argument to eliminate all spatstat packages for example, I have come across what you refer to about packages being dependent on each other. I don't know how to overcome this issue or whether it is advisable or safe to do so. – OpenSauce Jun 06 '21 at 15:04

1 Answers1

1

There's a character.only= argument in library(). To get detach() to work properly you simply need to add what sort of thing is to detach, in this case 'package:'

packagedelivery1 <- function(fry, leela) {
  if (fry) {
    library(leela, character.only=TRUE)
  } else {
    detach(sprintf('package:%s', leela), unload=TRUE, character.only=TRUE)
  }
}
packagedelivery1(TRUE, "matrixStats")
colSds(matrix(rnorm(9), 3, 3))
# [1] 1.6706355 0.5352099 1.4046043

packagedelivery1(FALSE, "matrixStats")  ## first unload
colSds(matrix(rnorm(9), 3, 3))
# Error in colSds(matrix(rnorm(9), 3, 3)) : 
#   could not find function "colSds"

packagedelivery2(FALSE, "lfe")          ## second unload (package not loaded)
# Error in detach(sprintf("package:%s", leela), unload = T, character.only = T) : 
#   invalid 'name' argument 

packagedelivery1(TRUE, "fooPackage")
# Error in library(leela, character.only = TRUE) : 
#   there is no package called ‘fooPackage’ 

Works as expected. And throws errors when package is not or no longer available.

You also could create a different function that warns instead of throwing errors, using require() and unloadNamespace():

packagedelivery2 <- function(fry, leela) {
  srh <- sprintf("package:%s", leela) %in% search()
  if (fry) {
    if (srh) {
      message(sprintf("Package called '%s' already loaded", leela))
    } else {
      require(leela, character.only=TRUE)
    }
  } else {
    if (!srh) {
      message(sprintf("There was no package called '%s'", leela))
    }
    unloadNamespace(leela)
  }
}

packagedelivery2(TRUE, "matrixStats")
colSds(matrix(rnorm(9), 3, 3))
# [1] 0.4954492 1.1789422 1.1264789

packagedelivery2(FALSE, "matrixStats")  ## first unload
colSds(matrix(rnorm(9), 3, 3))
# Error in colSds(matrix(rnorm(9), 3, 3)) : 
#   could not find function "colSds"

packagedelivery2(FALSE, "matrixStats")  ## second unload (package not loaded)
# There was no package called 'matrixStats'

packagedelivery2(TRUE, "fooPackage")
# Loading required package: fooPackage
# Warning message:
#   In library(package, lib.loc = lib.loc, character.only = TRUE, logical.return = TRUE,  :
#                there is no package called ‘fooPackage’

Note, that require() has an invisible output that you may use to install a missing package, just look into this famous answer.

jay.sf
  • 60,139
  • 8
  • 53
  • 110
  • This works, however, I have added an additional grepl argument to eliminate all packages containing my keyword. This reveals that certain packages are dependent upon each other, and therefore cannot be removed sequentially. I don't know if it is advisable or safe to go further than this. – OpenSauce Jun 06 '21 at 15:06