Metaprogramming in R from Hadley Wickham’s Advanced R

Han Oostdijk

2020/02/14

Date last run: 11Mar2020 (correction typo)

Introduction

Often having problems with non-standard evaluation I decided to read Hadley Wickham Advanced R chapters about metaprogramming.

Problem

An example of a problem I met was the case that I wanted to silently load the packages glue and purrr with the function HOQCutil::silent_library. This function accepted both a name and a character string (i.e as well knitr as 'knitr' ) but apparently not a list element containing the name of a package. With HOQCutil_0.1.16 we got the following results:

packages_to_load <- c('glue','purrr')
HOQCutil::silent_library
#> function (package_name,mywarnings = FALSE) {
#>   suppressWarnings({
#>     suppressPackageStartupMessages({
#>       library(
#>         as.character(as.name(substitute(package_name))) ,
#>         character.only = TRUE,
#>         warn.conflicts = mywarnings,
#>         quietly = !mywarnings,
#>         verbose = mywarnings
#>       )
#>     })
#>   })
#> }
#> <bytecode: 0x0000000017edff08>
#> <environment: namespace:HOQCutil>
HOQCutil::silent_library(knitr)
HOQCutil::silent_library('knitr')
purrr::walk(packages_to_load,HOQCutil::silent_library)
#> Error in as.name(substitute(package_name)): 'pairlist' object cannot be coerced to type 'symbol'

Solution

Reading the metaprogramming chapter I saw that I could use some rlang functions to fix the HOQCutil::silent_library function. It works now for all cases: a character string, a name and a variable with as value a character or name. The function is now included in the HOQCutil package (version 0.1.17). The following chunk shows how this works:

HOQCutil::silent_library
#> function (package_name,mywarnings = FALSE) {
#>   package_name2 <- rlang::enexpr(package_name)
#>   if (rlang::is_symbol(package_name2)) {
#>     package_name <- rlang::as_string(package_name2)
#>   }
#>   suppressWarnings({
#>     suppressPackageStartupMessages({
#>       library(
#>         package_name,
#>         character.only = TRUE,
#>         warn.conflicts = FALSE,
#>         quietly = TRUE,
#>         verbose = FALSE
#>       )
#>     })
#>   })
#> }
#> <bytecode: 0x00000000186aa9d0>
#> <environment: namespace:HOQCutil>

search()
#> [1] ".GlobalEnv"        "package:stats"     "package:graphics" 
#> [4] "package:grDevices" "package:utils"     "package:datasets" 
#> [7] "package:methods"   "Autoloads"         "package:base"
HOQCutil::silent_library(tabr)
HOQCutil::silent_library('tabraux')
packages_to_load <- c('glue','FactoMineR','dplyr')
purrr::walk(packages_to_load[1:2],HOQCutil::silent_library)
HOQCutil::silent_library(packages_to_load[[3]])
search()
#>  [1] ".GlobalEnv"         "package:dplyr"      "package:FactoMineR"
#>  [4] "package:glue"       "package:tabraux"    "package:tabr"      
#>  [7] "package:stats"      "package:graphics"   "package:grDevices" 
#> [10] "package:utils"      "package:datasets"   "package:methods"   
#> [13] "Autoloads"          "package:base"

While testing I realized that using the argument mywarnings=TRUE makes no sense. For compatibility reasons I will keep this argument but ignore it.

Session Info

This document was produced on 11Mar2020 with the following R environment:

  #> R version 3.6.0 (2019-04-26)
  #> Platform: x86_64-w64-mingw32/x64 (64-bit)
  #> Running under: Windows 10 x64 (build 18363)
  #> 
  #> Matrix products: default
  #> 
  #> locale:
  #> [1] LC_COLLATE=English_United States.1252 
  #> [2] LC_CTYPE=English_United States.1252   
  #> [3] LC_MONETARY=English_United States.1252
  #> [4] LC_NUMERIC=C                          
  #> [5] LC_TIME=English_United States.1252    
  #> 
  #> attached base packages:
  #> [1] stats     graphics  grDevices utils     datasets  methods   base     
  #> 
  #> other attached packages:
  #> [1] dplyr_0.8.5    FactoMineR_2.3 glue_1.3.1     tabraux_0.0.3  tabr_0.4.1    
  #> 
  #> loaded via a namespace (and not attached):
  #>  [1] Rcpp_1.0.3           pillar_1.4.3         compiler_3.6.0      
  #>  [4] tools_3.6.0          digest_0.6.23        evaluate_0.14       
  #>  [7] tibble_2.1.3         lifecycle_0.1.0      gtable_0.3.0        
  #> [10] lattice_0.20-38      pkgconfig_2.0.3      rlang_0.4.5         
  #> [13] ggrepel_0.8.1        xfun_0.10            stringr_1.4.0       
  #> [16] knitr_1.28           cluster_2.0.8        flashClust_1.01-2   
  #> [19] grid_3.6.0           tidyselect_0.2.5     scatterplot3d_0.3-41
  #> [22] R6_2.4.1             rmarkdown_2.1        purrr_0.3.3         
  #> [25] ggplot2_3.3.0        magrittr_1.5         scales_1.1.0        
  #> [28] htmltools_0.4.0      leaps_3.0            MASS_7.3-51.4       
  #> [31] assertthat_0.2.1     colorspace_1.4-1     stringi_1.4.6       
  #> [34] HOQCutil_0.1.18      munsell_0.5.0        crayon_1.3.4