I found this in the NAMESPACE file for a package:
export()
When I look at reference docs for export(), all the examples I find use an argument, e.g., export(myFunc), and I cannot locate an exact man page for export(). What will the above line do?
When documenting functions in a package, one will usually use the function export implying that the function that has been specified should be exported as part of the package.
The NAMESPACE holds information about functions imported from other packages as well as those exported from the package one is writing. Hence, under the NAMESPACE file, the export(myFunc) simply refers to a function that will be part of the package. It is nowadays normally not generated by hand and is done with roxygen2. An empty export() might be a design error because as the manual states:
Exports are specified using the export directive in the NAMESPACE file. A directive of the form
export(f, g)
specifies that the variables f and g are to be exported. (Note that variable names may be
quoted, and reserved words and non-standard names such as [<-.fractions must be.)
For more intuition, look at the error that occurs when you try to use a function not exported as part of a package.
stats::group_by
Error: 'group_by' is not an exported object from 'namespace:stats'
Related
I'm working on an R package at present and trying to follow the best practice guidelines provided by Hadley Wickham at http://r-pkgs.had.co.nz. As part of this, I'm aiming to have all of the package dependencies within the Imports section of the DESCRIPTION file rather than the Depends since I agree with the philosophy of not unnecessarily altering the global environment (something that many CRAN and Bioconductor packages don't seem to follow).
I want to use functions within the Bioconductor package rhdf5 within one of my package functions, in particular h5write(). The issue I've now run into is that it doesn't have its S3 methods declared as such in its NAMESPACE. They are declared using (e.g.)
export(h5write.default)
export(h5writeDataset.matrix)
rather than
S3method(h5write, default)
S3method(h5writeDataset, matrix)
The generic h5write is defined as:
h5write <- function(obj, file, name, ...) {
res <- UseMethod("h5write")
invisible(res)
}
In practice, this means that calls to rhdf5::h5write fail because there is no appropriate h5write method registered.
As far as I can see, there are three solutions to this:
Use Depends rather than Imports in the DESCRIPTION file.
Use library("rhdf5") or require("rhdf5") in the code for the relevant function.
Amend the NAMESPACE file for rhdf5 to use S3methods() rather than export().
All of these have disadvantages. Option 1 means that the package is loaded and attached to the global environment even if the relevant function in my package is never called. Option 2 means use of library in a package, which while again attaches the package to the global environment, and is also deprecated per Hadley Wickham's guidelines. Option 3 would mean relying on the other package author to update their package on Bioconductor and also means that the S3 methods are no longer exported which could in turn break other packages which rely on calling them explicitly.
Have I missed another alternative? I've looked elsewhere on StackOverflow and found the following somewhat relevant questions Importing S3 method from another package and
How to export S3 method so it is available in namespace? but nothing that directly addresses my issue. Of note, the key difference from the first of these two is that the generic and the method are both in the same package, but the issue is the use of export rather than S3method.
Sample code to reproduce the error (without needing to create a package):
loadNamespace("rhdf5")
rdhf5::h5write(1:4, "test.h5", "test")
Error in UseMethod("h5write") :
no applicable method for 'h5write' applied to an object of class
"c('integer', 'numeric')
Alternatively, there is a skeleton package at https://github.com/NikNakk/s3issuedemo which provides a single function demonstrateIssue() which reproduces the error message. It can be installed using devtools::install_github("NikNakk/s3issuedemo").
The key here is to import the specific methods in addition to the generic you want to use. Here is how you can get it to work for the default method.
Note: this assumes that the test.h5 file already exists.
#' #importFrom rhdf5 h5write.default
#' #importFrom rhdf5 h5write
#' #export
myFun <- function(){
h5write(1:4, "test.h5", "test")
}
I also have put up my own small package demonstrating this here.
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!)
export(drawHeatmap,drawHeatmap2,bubbleplot,...,heatmapBC)
# The classes are exported
exportClasses(BiclustMethod,Biclust,BCBimax,BCCC,BCXmotifs,BCSpectral,BCPlaid)
# Methods are exported
exportMethods(biclust,show,summary)
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
importClassesFrom(biclust,BiclustMethod,Biclust,BCBimax,BCCC,BCXmotifs,BCSpectral,BCPlaid)
# I import all the methods
importMethodsFrom(biclust,show,summary,biclust)
# I now export all of the previous again so I can use the doItAndPrint functionality in R Commander
export( drawHeatmap,...,biclustbarchart)
exportClasses(BiclustMethod,Biclust,BCBimax,BCCC,BCXmotifs,BCSpectral,BCPlaid)
exportMethods(biclust,show,summary)
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.
export(biclust,drawHeatmap,...,biclustbarchart)
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?
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.
I am writing an R package. Generally, I have some functions that they are not useful for external uses. So when I put them in Namespace file, it causes an error about documentation of functions. On the other hand, if I remove them from Namespace file, it causes another problem, Function not found. So, is there any way of calling a function without a need of writing documentations?
As Andrie commented if you want to include the function in the R package you need to put it inside a folder (e.g. packageparent/R/) and declare in NAMESPACE. You do not put a function in NAMESPACE.
IF you do not want to include it in your package, none of your functions in your package shall call this function, otherwise the package does not compile. You still can include this function in your package and not write any documentation for it.
To use this function outside your package just source it
How to define functions (methods) invisible to the user?
Those which are asterisked when you call methods() on them.
It seems there is everything about them on the internet, but how to define them?
Can I just define a non-visible function (by adding something to its name for example), or should I tweak the environment somehow, or is it a particular feature of R packages to hide stuff?
These are "hidden" functions. You might find this (warning pdf) useful. You can do it when you design a package in the NAMESPACE file included as part of the nuts and bolts of an R package. Here's the full text from the NAMESPACE file for the bilan package (can be found by opening up package source code tar.gz file from CRAN):
useDynLib(bilan)
exportPattern("^bil\\.[[:alpha:]]+")
exportPattern("^sbil\\.[[:alpha:]]+")
From the pdf mentioned above:
To have hidden functions. Replace the exportPattern command
with an export command, where export's arguments are
comma-separated function names that should be accessible to users
Basically, if you created an R package with two functions foo and bar, you could make NAMESPACE file with the line export(foo), and then bar would be a hidden function.
My R package uses an internal variable x. If I load the package (I've only tried using devtools::load_all), then x doesn't appear in the ls() list, but it does have a value. How can I avoid this?
I'm fine with the user being able to access the variable with myPackage::x, but not simply x.
The load_all function has an export_all argument.
From ?load_all
If TRUE (the default), export all objects. If FALSE, export only the objects that are listed as exports in the NAMESPACE file.
So, try using export_all=FALSE in your load_all call.
Try building the package first, and check whether the problem still exists. The exports from a package are defined in the NAMESPACE file. When you use devtools::load_all, the namespace isn't loaded ( see here). Read more about this and building a package in the manual Writing R extensions.
You might be using a default export pattern in your NAMESPACE file. Check it in your package, and if it looks like this:
exportPattern("^[^\\.]")
then the package exports everything from the namespace that doesn't start with a dot. So you either call it .x, or you change the exportPattern() to eg...
export(myfun1, myfun2)
to export the functions myfun1 and myfun2 from the package. By explicitly defining what you want to export, you avoid that something's available when there's no need for that.