最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

generics - UseMethod in one R package not finding method implemented in another package - Stack Overflow

programmeradmin2浏览0评论

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?

Share Improve this question asked Mar 14 at 22:22 AnikoAniko 18.9k4 gold badges50 silver badges45 bronze badges 2
  • Did you try using triple colons(:::)? 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
Add a comment  | 

1 Answer 1

Reset to default 1

While 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.

发布评论

评论列表(0)

  1. 暂无评论