TAGS :Viewed: 7 - Published at: a few seconds ago

[ Importing / Exporting packages using NAMESPACE ]

I am currently developing a plug-in for the R-Commander GUI. In this package I am using a great deal of other packages which I simply attached by using the Depends option in the description file. I am however now switching them over to the Imports option and am experiencing some problems with it. Because I want to use some functions not only internally in my own code, but also be able to print and use them in the script window of R Commander, I will also have to export them in the namespace.

Let's take for example the biclust package. This package has the following exports in its namespace:

# First a bunch of functions are exported (Note that the biclust function is not in here!)

# The classes are exported

# Methods are exported

So when I library(biclust) in an R session, it works as intended, meaning I can use the biclust method/function in the R console.

Now this how my namespace file looks like (or at least the part of it relevant to this discussion)

# I select those functions I need and import them.
importFrom(biclust, drawHeatmap,...,biclustbarchart)

# I import all the classes

# I import all the methods

# I now export all of the previous again so I can use the doItAndPrint functionality in R Commander
export( drawHeatmap,...,biclustbarchart)

However when I load in my own package now, it is not working as intended. While functions such as drawHeatmap are working, the biclust method/function can not be found.(Though I have clearly imported and exported the method.)

Seemingly the only way to get this working, is to put the biclust method also in the normal export() command.


Could someone clarify what I am doing wrong or what is going on here? Why are the same exports working for the biclust package, but not for my own package?

Answer 1

The only description of your error is that "it is not working as intended", so the following is a little stab in the dark.

It's useful to distinguish between methods and the generics that they are associated with. Biclust makes available both, and they are tightly associated. importFrom(biclust, biclust) imports the generic and associated methods, importMethodsFrom(biclust, biclust) imports the biclust methods defined in the biclust package, and implicitly the generic(s) on which the methods are defined. These are functionally equivalent so far; I think the original intention of importMethodsFrom() was when pkgA defines a generic, pkgB defines methods on the generic, and pkgD wants to use the generic from pkgA and the methods on that generic defined in pkgA and pkgB -- import(pkgA, foo), importMethodsFrom(pkgB, foo).

On the other end, when you say exportMethods(foo), it instructs R to make foo methods defined in your package available for others to use. But there are no foo methods defined in your package, so nothing is exported (maybe this should generate an error, or the methods that you import should be exported again). On the other hand, export(foo) tells R to export the foo generic, which is available for export -- it's the symbol that you'd imported earlier. (You mention that you "put the biclust method also in the normal export()", but actually it is the generic (and any methods associated with it) available for export.) So exporting biclust, rather than methods defined on it, seems to be what you want to do.

Normally, I would say that importing and then re-exporting functions or generics defined in other packages is not the right thing to do -- biclust, not your package, provides and documents the generic, and biclust would probably belong in Depends: -- presumably, many other functions from biclust are typically used in conjunction with the generic. Perhaps your Rcommander GUI is an exception.

Even though Imports: implies additional work (in the NAMESPACE file), it is usually the case that packages belong as Imports: rather than Depends: -- it makes the code in your package much more robust (imported functions are found in the package name space, rather than on the search path that the user can easily modify) and reduces the likelihood that the user experiences name clashes between identical symbols defined in different packages.