Importing two functions with same name using roxygen2
Asked Answered
D

3

27

I'm a maintainer of a CRAN package and get the following messages when loading:

* checking whether package ‘qdap’ can be installed ... [10s/10s] WARNING
Found the following significant warnings:
  Warning: replacing previous import ‘annotate’ when loading ‘NLP’
  Warning: replacing previous import ‘rescale’ when loading ‘scales’

Because I use the plotrix and scales packages as well as the NLP and ggplot packages. They have the functions rescale and annotate in common. This results in a significant warning with the latest CRAN check. So I decide to "fix" it.

I made the description something like this:

Package: qdap
Type: Package
Title: Bridging the gap between qualitative data and quantitative analysis
Version: 1.0.0
Date: 2013-06-26
Author: Tyler Rinker
Maintainer: Tyler Rinker <[email protected]>
Depends:
    R (>= 3.0.0),
    ggplot2 (>= 0.9.3.1),
    gdata,
    grid,
Imports:
    NLP,
    openNLP,
    plotrix,
    scales,
LazyData: TRUE
Description: Stuff
License: GPL-2

And added this to some .R files:

#' @import ggplot2 gridExtra RColorBrewer
#' @importFrom scales alpha

But this results in another warning:

* installing *source* package 'qdap' ...
** R
** data
*** moving datasets to lazyload DB
** inst
** preparing package for lazy loading
Warning: replacing previous import 'rescale' when loading 'scales'
Warning: replacing previous import 'annotate' when loading 'NLP'
Warning: replacing previous import 'alpha' when loading 'scales'

How do I use roxygen2's importFrom tag correctly?

I have read: https://github.com/hadley/devtools/wiki/Namespaces

But I learn best from an example where someone had to do this. I'm unsure of how to format the DESCRIPTION file correctly as well as the use of roxygen2 tags to avoid:

* checking whether package ‘qdap’ can be installed ... [10s/10s] WARNING
Found the following significant warnings:
  Warning: replacing previous import ‘annotate’ when loading ‘NLP’
  Warning: replacing previous import ‘rescale’ when loading ‘scales’

Here is the qdap GitHub Repo

Disaffect answered 20/8, 2013 at 19:13 Comment(11)
Note that you're still importing both packages though. There isn't a function specific way to import packages. Just look at your NAMESPACE file - you still have imports for all of the packages.Vanadium
Never import an entire package's NAMESPACE. Import all the symbols you need and no more. @import is evil. These "replacing previous import warnings" multiply as you start importing NAMESPACES that import other NAMESPACES.Robertson
@Robertson does this mean I have to go through and remove all @import and replace with: @importFrom? If only people named their functions in elvish and other obscure languages.Disaffect
@TylerRinker: welcome to the "Hates GSee" club. ;-)Marshland
You could switch to using Depends for everything so that you could at least suppress the "object is masked" messages, but using Depends has its own problems as I'm sure you know (and is not recommended except for the methods package) Here's a 4 hour old post from BDRRobertson
I would like to keep ggplot2 in depends but he conflicts with NLP. Is there a way to keep ggplot2 in depends and not have it squawk?Disaffect
FYI roxygen3 has @autoImports which mostly automatically figures out which functions to import.Hamartia
Another reason for hatred: never use Depends...Disused
@Robertson can you add that as an answer. It's not what I wanted but was the solution.Disaffect
@TylerRinker, but that would draw attention to the question and give people more opportunity to state their hatred for me. ;)Robertson
@Hamartia is roxygen3 and @autoImports no longer in the pipeline? I see on the repo "Roxygen development activity has shifted to roxygen2."Woodchuck
R
25

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.

Robertson answered 23/8, 2013 at 13:1 Comment(3)
If you imported two packages that each had a function foo into your package, couldn't you use the :: syntax to distinguish between the two? For example pkgA::foo() and pkgB::foo()? (Using importFrom should dramatically reduce the chances of having to do this)Antananarivo
@Antananarivo You can use pkgA::foo() to access foo from pkgA, but it will NOT import it into your package's namespace. Your package's namespace cannot have more than one function with the same name.Robertson
I use both gWidgets::gtable and gtable::gtable in my package, which give me a WARNING. Any suggestions on how to solve this?Peonage
G
4

Most likely no longer of use to you but maybe to others: the answer to your question can be found in the website you mention, in particular, here (quoting from source): "No matter how many times you use @importFrom foo bar".

So the correct use of roxygen2's tag @importFrom is: @importFrom package_name function_name. No commas, parenthesis, nothing, just the two names separated by a space (possibly applicable to more than 1 function, in the obvious way).

I have tried this myself just now when generating the documentation for the new version of one of my packages, so it should work.

I hope it helps.

Glovsky answered 17/8, 2016 at 16:12 Comment(0)
L
2

Recently I've found a new way to tackle this problem. I want to import dplyr as well as data.table in development which gives these warnings. To remove the overlap functions, I used importFrom to import every function in data.table except for the overlaps.

ls("package:data.table") %>% 
  setdiff(c("last","first","between",":=")) %>% 
  str_c(collapse = " ")

## "%between% %chin% %flike% %ilike% %inrange% %like% address alloc.col as.data.table as.Date.IDate as.IDate as.ITime as.xts.data.table chgroup chmatch chorder CJ copy cube data.table dcast dcast.data.table fcoalesce fifelse fintersect foverlaps frank frankv fread frollapply frollmean frollsum fsetdiff fsetequal fsort funion fwrite getDTthreads getNumericRounding groupingsets haskey hour IDateTime indices inrange is.data.table isoweek key key<- key2 like mday melt melt.data.table merge.data.table minute month nafill quarter rbindlist rleid rleidv rollup rowid rowidv second set set2key set2keyv setalloccol setattr setcolorder setDF setDT setDTthreads setindex setindexv setkey setkeyv setnafill setnames setNumericRounding setorder setorderv shift shouldPrint SJ tables test.data.table timetaken transpose truelength tstrsplit uniqueN update.dev.pkg wday week yday year"

the setdiff have included all the conflicted function names. Last I importFrom data.table only the functions above.

Ligature answered 6/12, 2019 at 13:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.