Importing Two Functions with Same Name Using Roxygen2

Importing two functions with same name using roxygen2

The thing to keep in mind is that you cannot have more than one function with
the same name in your package's namespace.

Suppose there are two packages, pkgA and pkgB, that both export a function
called foo. If you create a package, pkgC, that has import(pkgA) and
import(pkgB) in the NAMESPACE. Now, when you call library(pkgC) you'll get
a warning:

replacing previous import 'foo' when loading 'pkgB'. 

Now, suppose someone creates another package, pkgD, that has this in the NAMESPACE file:

import(pkgA)
import(pkgB)
import(pkgC)

Then, library(pkgD) will give 2 warnings:

1: replacing previous import ‘foo’ when loading ‘pkgB’ 
2: replacing previous import ‘foo’ when loading ‘pkgB’

If everyone adopts the practice of importing entire namespaces, then 30 years
from now, there will be a lot of these warnings.

Instead, since you can only have a single "foo" in your package, you should
explicitly import the "foo" (and other functions) that you want your package
to use. In the above example, the NAMESPACE for pkgD should be

importFrom(pkgB,foo)

If you actually need to use the two functions with the same name from two different packages, one hack you can perform is to import other functions from each package to ensure the packages are installed and their namespaces are loaded, but then refer to the functions you need using :: notation by placing this in your NAMESPACE:

importFrom(pkgA,foo)
importFrom(pkgB,bar)

and then calling functions pkgA::abc() and pkgB::abc() in your code.

Same function but with two different names in an R package using roxygen2?

Use

#' @rdname first
#' @export
second <- first

Your example

So if first.R initially looked like this

#' A function that adds 2
#' @name first
#' @usage first(x)
#' @param x a number
#' @export

first <- function(x) {
x + 2
}

Then simply include the extra lines of code like so (the last 3 lines are all that change)

#' A function that adds 2
#' @name first
#' @usage first(x)
#' @param x a number
#' @export

first <- function(x) {
x + 2
}

#' @rdname first
#' @export
second <- first

import the same PACKAGE in several R files

As mentioned in the comments, you only need to import it once, but importing it many times doesn't cause any problems.

If you don't want to import it in every function, but are worried about tying it to a single function (what if you only import it on function foo, but later you decided to replace foo with bar and lose the import) you can add all your shared import statements to NULL at the top of the document:

#' @import ggplot2
#' @import B
#' @import dplyr
NULL

roxygen2 will happily create the proper import statements in NAMESPACE, but you'll only have the imports listed once in a convenient place without tying them to any particular package

R with roxygen2: How to use a single function from another package?

If ldply() is important for your package's functionality, then you do want it in your package namespace. That is the point of namespace imports. Functions that you need, should be in the package namespace because this is where R will look first for the definition of functions, before then traversing the base namespace and the attached packages. It means that no matter what other packages are loaded or unloaded, attached or unattached, your package will always have access to that function. In such cases, use:

@importFrom plyr ldply

And you can just refer to ldply() without the plyr:: prefix just as if it were another function in your package.

If ldply() is not so important - perhaps it is called only once in a not commonly used function - then, Writing R Extensions 1.5.1 gives the following advice:

If a package only needs a few objects from another package it can use a fully qualified variable reference in the code instead of a formal import. A fully qualified reference to the function f in package foo is of the form foo::f. This is slightly less efficient than a formal import and also loses the advantage of recording all dependencies in the NAMESPACE file (but they still need to be recorded in the DESCRIPTION file). Evaluating foo::f will cause package foo to be loaded, but not attached, if it was not loaded already—this can be an advantage in delaying the loading of a rarely used package.

(I think this advice is actually a little outdated because it is implying more separation between DESCRIPTION and NAMESPACE than currently exists.) It implies you should use @import plyr and refer to the function as plyr::ldply(). But in reality, it's actually suggesting something like putting plyr in the Suggests field of DESCRIPTION, which isn't exactly accommodated by roxygen2 markup nor exactly compliant with R CMD check.

In sum, the official line is that Hadley's advice (which you are quoting) is only preferred for rarely used functions from rarely used packages (and/or packages that take a considerable amount of time to load). Otherwise, just do @importFrom like WRE advises:

Using importFrom selectively rather than import is good practice and recommended notably when importing from packages with more than a dozen exports.

import all the functions of a package except one when building a package

The NAMESPACE file is somewhat flexible here, as described in Writing R Extensions.

The two main import directives are:

import(PACKAGE)

which imports all objects in the namespace into your package. The second option is to do specific imports using:

importFrom(PACKAGE, foo)

which gives you access to foo() without needing the fully qualified reference PACKAGE::foo().

But these aren't the only two options. You can also use the except argument to exclude just a handful of imports:

import(PACKAGE, except=c(foo,bar))

which gives you everything from PACKAGE's namespace but foo() and bar(). This is useful - as in your case - for avoiding conflicts.

For roxygen, great catch on figuring out that you can do:

#' @rawNamespace import(PACKAGE, except = foo)

to pass a raw NAMESPACE directive through roxygen.



Related Topics



Leave a reply



Submit