I am trying to build an R package that uses features implemented the nspmix
R package. That package implements a generic optimization method in the cnm
function, and to use it one is supposed to create objects of a custom class and implement specific methods for it.
I am creating objects of class npkm
:
#' @export
npkm <- function(time, censor){
res <- list(time = time, censor = censor)
class(res) <- "npkm"
res
}
Then I need to implement, for example, a gridpoints
method for my class (there is a bunch of other required methods):
#' @export
gridpoints.npkm = function(x, beta, grid=100) {
tms <- x$time
pp = unique(quantile(tms, seq(0, 1, len=grid), type = 1))
pp
}
The gridpoints
function is defined as an internal function of the nspmix
package as follows:
gridpoints = function(x, beta, grid) UseMethod("gridpoints")
This works perfectly as long as my gridpoints.npkm
function is sourced and is in the global environment. But I want to create a package that uses this optimization method. And once I put gridpoints.npkm
in a package, even exporting it, whenever I call the optimization function cnm
(which would call gridpoints
at some point), I get an error that UseMethod("gridpoints")
cannot find my method (no applicable method for 'gridpoints' applied to an object of class "npkm"). As soon as I put my function into the global environment, instead of having it in the package namespace, everything is fine.
I have tried importing the gridpoints
function from the nspmix
package, but I can't, because it is not exported. I have tried adding the same definition to my package, but the nspmix::cnm
function is not calling it, naturally.
The documentation for UseMethod
has some text that seems relevant, and maybe explains why UseMethod
is not finding my function in a different package, but I am not quite sure what is it suggesting as a solution:
Namespaces can register methods for generic functions. To support this, UseMethod and NextMethod search for methods in two places: in the environment in which the generic function is called, and in the registration data base for the environment in which the generic is defined (typically a namespace). So methods for a generic function need to be available in the environment of the call to the generic, or they must be registered. (It does not matter whether they are visible in the environment in which the generic is defined.) As from R 3.5.0, the registration data base is searched after the top level environment (see topenv) of the calling environment (but before the parents of the top level environment).
So, is there a magic incantation I could use to make this work? Perhaps declare gridpoints
a generic function? Or would that need to be done in the nspmix
package?
I am trying to build an R package that uses features implemented the nspmix
R package. That package implements a generic optimization method in the cnm
function, and to use it one is supposed to create objects of a custom class and implement specific methods for it.
I am creating objects of class npkm
:
#' @export
npkm <- function(time, censor){
res <- list(time = time, censor = censor)
class(res) <- "npkm"
res
}
Then I need to implement, for example, a gridpoints
method for my class (there is a bunch of other required methods):
#' @export
gridpoints.npkm = function(x, beta, grid=100) {
tms <- x$time
pp = unique(quantile(tms, seq(0, 1, len=grid), type = 1))
pp
}
The gridpoints
function is defined as an internal function of the nspmix
package as follows:
gridpoints = function(x, beta, grid) UseMethod("gridpoints")
This works perfectly as long as my gridpoints.npkm
function is sourced and is in the global environment. But I want to create a package that uses this optimization method. And once I put gridpoints.npkm
in a package, even exporting it, whenever I call the optimization function cnm
(which would call gridpoints
at some point), I get an error that UseMethod("gridpoints")
cannot find my method (no applicable method for 'gridpoints' applied to an object of class "npkm"). As soon as I put my function into the global environment, instead of having it in the package namespace, everything is fine.
I have tried importing the gridpoints
function from the nspmix
package, but I can't, because it is not exported. I have tried adding the same definition to my package, but the nspmix::cnm
function is not calling it, naturally.
The documentation for UseMethod
has some text that seems relevant, and maybe explains why UseMethod
is not finding my function in a different package, but I am not quite sure what is it suggesting as a solution:
Namespaces can register methods for generic functions. To support this, UseMethod and NextMethod search for methods in two places: in the environment in which the generic function is called, and in the registration data base for the environment in which the generic is defined (typically a namespace). So methods for a generic function need to be available in the environment of the call to the generic, or they must be registered. (It does not matter whether they are visible in the environment in which the generic is defined.) As from R 3.5.0, the registration data base is searched after the top level environment (see topenv) of the calling environment (but before the parents of the top level environment).
So, is there a magic incantation I could use to make this work? Perhaps declare gridpoints
a generic function? Or would that need to be done in the nspmix
package?
1 Answer
Reset to default 1While writing up all the things I have tried, I had another idea and it worked: I have to explicitly declare my function to be a method of the nspmix::gridpoints
generic function (even though it is not exported from the namespace).
#' @exportS3Method nspmix::gridpoints npkm
gridpoints.npkm = function(x, beta, grid=100) {
tms <- x$time
pp = unique(quantile(tms, seq(0, 1, len=grid), type = 1))
pp
}
This adds S3method(nspmix::gridpoints,npkm)
into the NAMESPACE.
:::
)? That's the infix operator to retrieve internal methods. – IRTFM Commented Mar 15 at 23:18:::
did NOT work - that was more natural to me as well. I get the following warning: "S3 method ‘nspmix:::gridpoints.npkm’ was declared in NAMESPACE but not found" – Aniko Commented Mar 17 at 14:50