I'm writing some R functions that employ some useful functions in other packages like stringr
and base64enc
. Is it good not to call library(...)
or require(...
) to load these packages first but to use ::
to directly refer to the function I need, like stringr::str_match(...)
?
Is it a good practice in general case? Or what problem might it induce?
It all depends on context.
::
is primarily necessary if there are namespace collisions, functions from different packages with the same name. When I load thedplyr
package, it provides a functionfilter
, which collides with (and masks) thefilter
function loaded by default in thestats
package. So if I want to use thestats
version of the function, I'll need to call it withstats::filter
. This also gives motivation for not loading lots of packages. If you really only want one function from a package, it can be better to use::
than load the whole package, especially if you know the package will mask other functions you want to use.Not in code, but in text, I do find
::
very useful. It's much more concise to typestats::filter
than "thefilter
function in thestats
package".From a performance perspective, there is a (very) small price for using
::
. Martin Maechler wrote (on the r-devel mailing list (Sept 2017))The performance penalty is very small, on the order of a few microseconds, so it's only a concern when you need highly optimized code. Running a line of code that uses
::
one million times will take a second or two longer than code that doesn't use::
.As far as portability goes, it's nice to explicitly load packages at the top of a script because it makes it easy to glance at the first few lines and see what packages are needed, installing them if necessary before getting too deep in anything else, i.e., getting halfway through a long process that now can't be completed without starting over.
Aside: a similar argument can be made to prefer
library()
overrequire()
. Library will cause an error and stop if the package isn't there, whereas require will warn but continue. If your code has a contingency plan in case the package isn't there, then by all means useif (require(package)) ...
, but if your code will fail without a package you should uselibrary(package)
at the top so it fails early and clearly. (Thanks to Hugh and BondedDust in the comments.)Writing your own package
The general solution is to make your own package that
imports
the other packages you need to use in the DESCRIPTION file. Those packages will be automatically installed when your package is installed, so you can usepkg::fun
internally. Or, by also importing them in theNAMESPACE
file, you canimport
an entire package or selectivelyimportFrom
specific functions and not need::
. Opinions differ on this. R-Core member Martin Maechler (same r-devel source as above) says:On the other hand, prominent package developer Hadley Wickham says in his R Packages book:
With two esteemed R experts giving opposite recommendations, I think it's fair to say that you should pick whichever style suits you best and meets your needs for clarity, efficiency, and maintainability.
If you frequently find yourself using just one function from another package, you can copy the code and add it to your own package. For example, I have a package for personal use that borrows
%nin%
from theHmisc
package because I think it's a great function, but I don't often use anything else fromHmisc
. Withroxygen2
, it's easy to add@author
and@references
to properly attribute the code for a borrowed function. Also make sure the package licenses are compatible when doing this.