-
Notifications
You must be signed in to change notification settings - Fork 758
Namespaces
This brief guide introduces you to namespaces and best practices for their use in conjunction with Roxygen.
- imports
- suggests
- depends
- enhaces
Namespaces make it easier to come up with you own function names without worrying about what names other packages have used. A namespace means you can use any name you like for internal functions, and when there is a conflict with an exported function, there is a standard disambiguation procedure.
It's not always easy to tell whether or not a function is internal or external. A few rules of thumb:
-
Is the purpose of the function different to the purpose of the package? If not, make it internal. (A package should provide a set of closely related functions for a well-defined problem domain - someone should be able to look at all the functions in your package and say this is a package about X - if not, you should consider splitting it up into two packages)
-
Does the function have a clear purpose and can you easily explain it? Every external function needs to be documented, and there's an implicit contract that that function will continue to exist in the future. If that's not the case, don't export it.
If a function isn't exported, you don't need to document it. This doesn't mean you shouldn't document it, but you only need to if it's complicated enough that you think you won't remember what it does.
To export a function, use the roxygen @export
tag.
There are two ways to access functions from other packages: with depends or imports. It's better to import packages rather than depending on them, because imported packages don't get loaded in a way the user can see. This is good practice because it reduces the chances of conflict, and it makes the code clearer by requiring the every package used be explicitly loaded. For example, ggplot2 currently depends on the plyr package - this means that once you've loaded ggplot2, you don't need to load plyr to get access to (e.g) ddply
. This is bad because you can't see which packages a block of code uses. The rest of this section describes how to use imports.
To import a package, it needs to appear in two places:
-
In the
Imports
line in yourDESCRIPTION
file. It's good practice to include the version number of the package as well, even though this is currently only checked byR CMD check
, not when the package is loaded -
In your
NAMESPACE
file, as generated by the@imports
roxygen tag. The best place to put this tag is the documentation file for your entire package (you do have one, right?!)
There are two alternatives to using @imports
, but these are not currently recommended, as described below:
-
@importFrom
imports only selected functions from another package. This is currently a pain in roxygen because it doesn't automatically remove duplicates - this means that if you use a function in more than one place, you have to arbitrarily choose where to import it. For this reason, I currently recommend using@imports
in the documentation for the package. -
::
refers to a function within a package directly. I don't currently recommend it because it doesn't work well in combination with devtools - it will always use the installed version, rather than the development version
Other types of imports:
-
Compiled code: If you have C or Fortran code in your package, you'll need to add
@useDynLib mypackage
to your package documentation to ensure your functions can access it. This also means you don't need to specifyPACKAGE
in.Call
. -
S3 methods: If you are adding a new S3 method for an existing function, use
@S3method function class
instead of@export
. If you have created a new generic function, use@export
to export it, and then@S3method
for its methods. -
S4 methods: See the R extensions manual
You should very very very rarely use :::
. This is a sign that you're using an internal function from someone else - and there is no guarantee that that function won't change from version to version. It would be better to encourage the author to make it an external, exported function, or ask if you could include a copy of it in your package.