-
Couldn't load subscription status.
- Fork 151
Description
This function provides a much better user experience for code using 'suggests' packages over some formulation of
if (requireNamespace("x", quietly = TRUE)).
However, it's much more expensive to use (a full 3 orders of magnitude):
bench::mark(rlang::check_installed("later"), requireNamespace("later", quietly = TRUE), check = FALSE)
#> # A tibble: 2 × 6
#> expression min median `itr/sec` mem_alloc `gc/sec`
#> <bch:expr> <bch> <bch:> <dbl> <bch:byt> <dbl>
#> 1 "rlang::check_installed(\"later\")" 397µs 443µs 2189. 5.54MB 17.0
#> 2 "requireNamespace(\"later\", quietl… 558ns 613ns 1294407. 0B 0Created on 2025-02-12 with reprex v2.1.1
In purrr, I employ caching to ensure it's not run time every time a function is called e.g. https://github.com/tidyverse/purrr/blob/main/R/map.R#L214-L217 but I notice in other codebases it's often used unconditionally at the top of a function body (FYI @hadley).
Rather than require the user to implement these optimizations, it might be nice to handle this at source by short-cutting detection if the package is already loaded. This can be easily done using .getNamespace(), a really cheap function which returns either the namespace environment if already loaded or else NULL.
Note that this would be different to current behaviour as check_installed() actually checks if the package is installed on disk (which contributes to the slowness). Hence a question is: do we hide this behind an argument, or would it be cleaner to introduce another function e.g. check_available()?