Suppose I'm developing a package, called foo
, which would like to use the description
function from the memisc
package. I don't want to import the whole memisc
namespace because :
memisc
overrides the base aggregate.formula
function, which breaks several things. For example, example(aggregate)
would fail miserably.The package includes the following files :
DESCRIPTION
Package: foo Version: 0.0 Title: Foo Imports: memisc Collate: 'foo.R'
NAMESPACE
export(bar) importFrom(memisc,description)
R/foo.R
##' bar function ##' ##' @param x something ##' @return nothing ##' @importFrom memisc description ##' @export `bar` <- function(x) { description(x) }
I'd think that using importFrom
would not load the entire memisc
namespace, but only namespace::description
, but this is not the case. Starting with a vanilla R :
R> getS3method("aggregate","formula") ## ... function code ... ## <environment: namespace:stats> R> library(foo) R> getS3method("aggregate","formula") ## ... function code ... ## <environment: namespace:memisc> R> example(aggregate) ## Fails
So, do you know how I can import the description
function from memisc
without getting aggregate.formula
in my environment ?
As of R 3.6, importing only one or more functions without having the load the complete namespace can be done using the include.only argument of the require and library functions. In the following snippet, you can find some examples using the stringr package. One can also load all functions from a namespace, but exclude a selection. Like this:
Importing the whole namespace is no longer required. As of R 3.6, importing only one or more functions without having the load the complete namespace can be done using the include.only argument of the require and library functions. In the following snippet, you can find some examples using the stringr package.
As of R 3.6, importing only one or more functions without having the load the complete namespace can be done using the include.only argument of the require and library functions. In the following snippet, you can find some examples using the stringr package.
Whether you import a module or import a function from a module, Python will parse the whole module. Either way the module is imported. "Importing a function" is nothing more than binding the function to a name. In fact import module is less work for interpreter than from module import func.
You can't.
If you declare memisc
in the Imports:
field, the namespace will be loaded when the package is loaded and the exported objects will be findable by your package. (If you specify it in Depends:
, the namespace will be loaded and attached to the search path which makes the exported objects findable by any code.)
Part of loading a namespace is registering methods with the generic. (I looked but couldn't find a canonical documentation that says this; I will appeal to the fact that functions are declared as S3 methods in the NAMESPACE
file as evidence.) The defined methods are kept with the generic and have the visibility of the generic function (or, perhaps, the generic function's namespace).
Typically, a package will define a method either for a generic it creates or for a class it defines. The S3 object system does not have a mechanism for formally defining an S3 class (or what package created the class), but the general idea is that if the package defines functions which return an object with that class attribute (and is the only package that does), that class is that package's class. If either of these two conditions hold, there will not be a problem. If the generic is defined in the package, it can only be found if the package is attached; if the class is defined in the package, objects of that class would only exist (and therefore be dispatched on) if the package is attached and used.
In the memisc
example, neither holds. The aggregate
generic is defined in the stats
package and the formula
object is also defined in the stats
package (based on that package defining as.formula
, [.formula
, etc.) Since it is neither memisc
's generic nor memisc
's object, the effects can be seen even (and the method dispatched to) if memisc
is simply loaded but not attached.
For another example of this problem, but with reorder.factor
, see Reordering factor gives different results, depending on which packages are loaded.
In general, it is not good practice to add methods to generics for which the package does not control either the object or the generic; doubly so if it overrides a method in a core package; and egregiously so if it is not a backwards compatible function to the existing function in the core packages.
For your example, you may be better off copying the code for memisc::describe
into your package, although that approach has its own problems and caveats.
With the caveat that I'm not too familiar with the R environment and namespaces, nor whether this would work in a package — a workaround I've used in programming is to use ::
to copy the function into my own function.
It may have unknown consequences of loading the whole package, as discussed in the comments to OP's question, but it seems to not attach the package's function names to R namespace and mask existing function names.
Example:my_memisc_description <- memisc::description
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With