S3 method consistency warning when building R package with Roxygen
I think this happens because a method must have all the same arguments as the generic. So add ...
to the arguments of common.list()
. Like this:
common.list <- function(word.list, overlap = "all", equal.or = "more", ...)
Similarly, common.default()
should have word.list
as an argument.
r - S3 generic/method consistency when different arguments needed
I am not sure I would use S3 here. Not answering your specific question, but consider something like this. Of course, this is irrelevant if your actual use case is far enough away from your example.
foo <- function(x, y) {
if (is.list(x)) return(do.call(foo, x))
paste(x, y)
}
So now you can get the behavior you want, and just document x
as being a list of arguments or the first argument. Otherwise, you'll create some annoying things such as requiring the user to explicitly name the argument every time.
foo("a", "b")
# [1] "a b"
foo(list(x = "a", y = "b"))
# [1] "a b"
foo(list(y = "a", x = "b"))
# [1] "b a"
foo("a", "b", z = "c")
# Error in foo("a", "b", z = "c") : unused argument (z = "c")
foo(list("a", "b", z = "c"))
# Error in (function (x, y) : unused argument (z = "c")
If compelled, you can accomplish the same thing using S3. But either way, you probably want to just name the argument the same thing and document it as having two meanings.
foo <- function(x, y, ...) UseMethod('foo')
foo.default <- function(x, y, ...) paste(x, y)
foo.list <- function(x, y, ...) do.call(foo, x)
An example of this is the plot
function in base.
x
the coordinates of points in the plot. Alternatively, a single plotting structure, function or any R object with a plot method can be provided.y
the y coordinates of points in the plot, optional if x is an appropriate structure.
Here, x
is either the x coordinate or a valid plotting structure. And then y
is only used if needed.
S3 method help (roxygen2)
The bug you are seeing is mostly likely caused because the list method of the common generic is not being exported, so common.default
gets called instead. You can pick up this problem using devtools::missing_s3
- the function is a bit heuristic, so you may get a few false positives (e.g. it can't currently tell that is.list
isn't a method). This is an incredibly common problem (it has caught me so many times), and the next iteration of roxygen will do more to prevent it.
Currently, to correctly export S3 methods with roxygen you need to do either:
@S3method generic class
(and nothing else) if you don't want to document the method@method generic class
and@export
if you want to export and document it.
You should never have @S3method
and @method
in the same documentation block.
Update for roxygen2 >3.0.0
Now roxygen automatically figures out if a function is an S3 method so:
- Never use
@S3method
or@method
- Use
@export
if you want the method to be exported (which you normally do, even if the generic isn't)
S3 generic/method consistency - How to dispatch according to chosen type?
In the code in the question MyFun
is not a generic and MyFun.algo1
and MyFun.algo2
are not S3 methods even though the names seem to suggest that. It would be beter to change it to something like this which is not suggestive of something it is not, won't trigger any checks and is more compact.
Myfun <- function(x, type = c("algo1", "algo2"), A, B, ...) {
type <- match.arg(type)
do.call(type, list(x, A, B, ...))
}
algo1 <- function(x, A, B, ...) "algo1"
algo2 <- function(x, A, B, ...) "algo2"
# test run
Myfun(1, "algo1", 2, 3)
## [1] "algo1"
# another test run
Myfun(1, A = 2, B = 3)
## [1] "algo1"
Roxygen2 - how to properly document S3 methods
The @method
tag generates \method entries in the \usage field in Rd files.
The @S3method
tag generates S3method() entries in the NAMESPACE file.
The @export
tag generates export() entries in the NAMESPACE file.
Here is my example:
#' A description of MyHappyFunction
#'
#' A details of MyHappyFunction
#'
#' @title MyHappyFunction: The my happy function
#' @param x numeric number
#' @param ... other arguments
#' @examples
#' a <- 1
#' class(a) <- "lm"
#' MyHappyFunction(a)
#'
#' @rdname MyHappyFunction
#' @export MyHappyFunction
MyHappyFunction <- function(x, ...){
UseMethod("MyHappyFunction")
}
#' @return \code{NULL}
#'
#' @rdname MyHappyFunction
#' @method MyHappyFunction lm
#' @S3method MyHappyFunction lm
MyHappyFunction.lm = function(x, ...) {
# do some magic
}
#' @return \code{NULL}
#'
#' @rdname MyHappyFunction
#' @method MyHappyFunction default
#' @S3method MyHappyFunction default
MyHappyFunction.default = function(x, ...) {
# do some magic
}
3 From the wiki page...
I guess that it means "you do not write @S3method generic mymethod myobject
."
Importing a package's S3 methods without importing its functions
Iñaki Úcar's mention of the @rawNamespace
tag led me to work out a version that doesn't import any of package B's exported functions, using the getNamespaceExports
function mentioned in this answer:
#' @rawNamespace import(packageB, except = getNamespaceExports("packageB"))
The @rawNamespace
tag in roxygen2
inserts raw code into the NAMESPACE file. getNamespaceExports
returns the names of all exported functions in a namespace: this can be a package that you haven't attached.
For my specific example, I can write this:
#' @import simmer
#' @rawNamespace import(simmer.plot, except = getNamespaceExports("simmer.plot"))
which puts these lines in the NAMESPACE:
import(simmer)
import(simmer.plot, except = getNamespaceExports("simmer.plot"))
R package documentation: Found the following apparent S3 methods exported but not registered
I don't know Roxygen2
very well, but it appears that you have declared is.nan.data.frame
to be the is.nan
method for class data.frame
. Since you did that, you should call it as is.nan(df)
in the help page example.
If you don't want it to be the method, you just want it to be a regular function using dots in the name, then you shouldn't have @method is.nan data.frame
. But you indicate that you do want it to be a method.
Edited to add: Just to summarize your comments, the following fixes got rid of all the errors:
- use @export by itself without naming the function (as suggested by @KonradRudolph)
- remove the @usage line
- use
is.nan(df)
in the example (as I suggested)
Related Topics
Using Strsplit and Subset in Dplyr and Mutate
Removing a List of Columns from a Data.Frame Using Subset
Convert Begin and End Coordinates into Spatial Lines in R
Model Matrix with All Pairwise Interactions Between Columns
Joining Two Datasets Using Fuzzy Logic
Passing by Reference a Data.Frame and Updating It with Rcpp
R: How to Make a Barplot with Labels Parallel (Horizontal) to Bars
R: Data.Table Count !Na Per Row
How to Plot the Linear Regression in R
Remove Duplicate Values Based on 2 Columns
What Is R's Crossproduct Function
How to Rotate the X-Axis Labels 90 Degrees in Levelplot
How Can Library() Accept Both Quoted and Unquoted Strings