Skip to content
hadley edited this page Oct 19, 2010 · 25 revisions

Intro to namespaces

This brief guide introduces you to namespaces and best practices for their use in conjunction with Roxygen.

Package dependencies

  • imports
  • suggests
  • depends
  • enhaces

Why use a namespace?

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.

Internal vs. external

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.

Exporting functions

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.

Importing functions

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 your DESCRIPTION file. It's good practice to include the version number of the package as well, even though this is currently only checked by R 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 specify PACKAGE 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.

Clone this wiki locally