As the name suggest, namespaces provide “spaces” for “names”, providing a context for evaluating which object is found when you look for it. When developing code, they allow you to specify which package to look for a function when there are multiple packages it could come from, and when developing packages they ensure that your functions always call functions in the same place.
Namespaces make it possible for packages to refer to specific functions in other packages, not the functions that you have defined in the global workspace.
For example, take the simple
nrow # function (x) # dim(x)[1L]
What happens if we create our own dim method? Does
dim <- function(x) c(1, 1) dim(mtcars) nrow(mtcars)
Suprisingly, it does not! That’s because when
nrow looks for an object called
dim, it finds the function in the base package, not our function.
Namespaces also provide an extension to the standard way of looking up the value of an object: instead of just typing
objectname, you type
Namespaces also control the functions and methods that your package makes available for use by others. Namespaces make it easier to come up with your 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.
The easiest way to use namespaces is with roxygen2, because it keeps the namespace definitions next to the function that it concerns. The translation between roxygen2 tags and
NAMESPACE directives is usually straightforward: the tag becomes a function name and its space-separated arguments become comma separated arguments to the function. For example
@import plyr becomes
@importFrom plyr ddply becomes
importFrom(plyr, ddply). The chief exception is
@export which will automatically figure out the function name to export.
How do namespaces work
For every function in your package, you need to decide whether it is external and available to all users of the package, or internal and only available to other functions within the package. 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 the same as 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. Generally, you want to export as few functions as possible: this makes it easier to change the package in the future.
As described below, the
@export tag is all that you need. There are only a few exceptions:
Functions: use the
S3 methods: There are two ways to export a method for an S3 method depending on whether it’s documented or not:
If it’s documented, you’ll already be using the
@methodtag to state that it’s an S3 method and you only need the
@exportto generate the correct export flag in the
If it’s not documented, use the
@S3method function class
S4 classes: Use
S4 methods: If the methods are for classes that you have defined and exported, you don’t need to do anything. If they are for classes defined in other packages, you need to use
Other objects: For any other types of object that you want to make available to the user, use
You may also want to make the distinction between functions for users and functions for other developers. Functions that might be useful for developers or power users should be exported, but tagged with
@keywords internal so they don’t show up in routine lists of function documentation.
In your package
DESCRIPTION there are two ways to indicate that your package requires another package to work: by listing it in either
Depends works just like using library to load a package, but
Imports is a little more subtle: the dependency doesn’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 that every package used be explicitly loaded. Since R 2.14 there is no reason to use
Depends because all packages have a namespace.
There are two places you need to record your package’s dependency:
Importsfield in the
DESCRIPTIONfile, used by
install.packagesto download package dependencies automatically.
NAMESPACEfile, to make all the functions in the dependency available to your code. The easiest way to do this is to add
@import package-nameto your package documentation:
#' @docType package #' ... #' @import stringr MASS
roxygen2 generate the
NAMESPACE file from that.
There are two alternatives to using
@importFrom package fun1 fun2 ...to only import selected functions from another package. This is important if you are importing two packages share functions with the same name. You can also use it to produce a very specific
NAMESPACE, but at the cost of having to use
@importFromfor every function that uses a function from another package.
::refers to a function within a package directly. I don’t recommend this method because it doesn’t work well during package development – it will use the installed version of the package, rather than the development version.
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.
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 means you don’t need to specify
How do they work
New set of rules on top of ordinary [[scoping]] rules, which deal with lists of environments - each environment belongs to a package. Search path. Variable look up differs depending on whether you’re inside or outside a package. If a package has a namespace, then R looks first inside the package namespace, then the imports, then the base namespace and then the normal search path.