17

I've got a package which a whole bunch of miscellaneous functions (see What to do with imperfect-but-useful functions? ). Because the functions are not particularly related, they depend on a whole bunch of other packages. Often there will be just one function in the whole package which uses another package. Yet if I use Imports, Suggests, or Depends in the DESCRIPTION file, the whole list of packages will be loaded each time my package is loaded, even though very few of them are needed by any given user.

Is there any way to just load the dependencies only when a particular function is used? I could put a call to library() inside the function themselves, but that seems like bad practice since it doesn't tell the package management system anything and therefore the user might not have it installed.

Community
  • 1
  • 1
Ari B. Friedman
  • 71,271
  • 35
  • 175
  • 235

2 Answers2

17

You can use Suggests, and in the function that needs the package you can add code to require() said package and if not available throw an error. An example I am familiar with, the vegan package, has, in its DESCRIPTION

Depends: permute
Suggests: MASS, mgcv, lattice, cluster, scatterplot3d, rgl, tcltk

and on loading the package we have:

R> require(vegan)
Loading required package: vegan
Loading required package: permute
This is vegan 1.90-0

and sessionInfo() reports that none of the Suggested packages has yet been loaded/attached etc:

R> sessionInfo()
R version 2.13.1 Patched (2011-07-29 r56550)
Platform: x86_64-unknown-linux-gnu (64-bit)

locale:
 [1] LC_CTYPE=en_GB.utf8       LC_NUMERIC=C             
 [3] LC_TIME=en_GB.utf8        LC_COLLATE=en_GB.utf8    
 [5] LC_MONETARY=C             LC_MESSAGES=en_GB.utf8   
 [7] LC_PAPER=en_GB.utf8       LC_NAME=C                
 [9] LC_ADDRESS=C              LC_TELEPHONE=C           
[11] LC_MEASUREMENT=en_GB.utf8 LC_IDENTIFICATION=C      

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] vegan_1.90-0  permute_0.5-0

loaded via a namespace (and not attached):
[1] tools_2.13.1
Gavin Simpson
  • 170,508
  • 25
  • 396
  • 453
  • 4
    +1 this strategy is probably the appropriate one for a misc package: `Suggest`ed packages do not need to be installed in order to install your package. For a misc package that can be a great advantage. E.g. users can use the non-rgl part of vegan even if rgl cannot be installed on their machine. Only the rgl-using functions are not available in this case. – cbeleites unhappy with SX Aug 01 '11 at 10:13
  • @cbeleites That is the very reason Jari Oksanen (lead vegan developer) chose to use Suggests for the extra packages we use. – Gavin Simpson Aug 01 '11 at 11:20
  • Better than `require`, you might want to use `requireNamespace` and `::`. See http://r-pkgs.had.co.nz/description.html for more details. – Dan Chaltiel Aug 02 '20 at 12:59
17

In general, I try to avoid using require() in packages. As a suggestion, work with a namespace (that's not difficult) and use Imports : packages mentioned there are not loaded. You can import only a single function from another package by :

  • using importFrom declaration in the namespace file. importFrom(foo, x, y) tells that functions x and y from package foo should be imported.
  • using the double colon operator in your code : foo::bar imports function bar from package foo. eg. plyr::ddply(...) will access the ddply function without the package is loaded
  • or the triple colon operator in case of objects that are not exported (foo:::bar)

In all three cases, the packages should be mentioned in Imports. See also the relevant chapter 1.6 and others in Writing R Extensions.

EDIT : As @Gavin pointed out, this all works only when importing from a package with an own namespace apparently. From next version of R on (2.14?) all packages should have a namespace.

Joris Meys
  • 106,551
  • 31
  • 221
  • 263