If a package has

    importClassesFrom(P, C)

in its NAMESPACE, then should it _also_ have

    importClassesFrom(P, <superclasses of C exported from P>)
    importClassesFrom(Q, <superclasses of C exported from Q>)
    ## and so on

... ?  I think that WRE could be more clear on this point, and in any case
I _think_ that the answer is yes.

Notably, I think that this rule would resolve some of the problems
with stale caches that I described in this thread from September:

    https://stat.ethz.ch/pipermail/r-devel/2022-September/081971.html

I've attached a script demonstrating my point.  It creates and installs a
package named TestPackage with

    importClassesFrom(Matrix, dgCMatrix, CsparseMatrix)

in NAMESPACE and

    setClass("whatever", contains = "dgCMatrix")

in R/*.R.  After installing the package, I see:


> ns <- asNamespace("TestPackage")
> names(ns)
 [1] ".__C__generalMatrix"  ".__C__Matrix"         ".__C__sparseMatrix"
 [4] ".__C__compMatrix"     ".__C__whatever"       "zzz"
 [7] ".packageName"         ".__C__dsparseMatrix"  ".__NAMESPACE__."
[10] ".__C__dMatrix"        ".__S3MethodsTable__."
> sort(names(ns))
 [1] ".__C__Matrix"         ".__C__compMatrix"     ".__C__dMatrix"
 [4] ".__C__dsparseMatrix"  ".__C__generalMatrix"  ".__C__sparseMatrix"
 [7] ".__C__whatever"       ".__NAMESPACE__."      ".__S3MethodsTable__."
[10] ".packageName"         "zzz"
> sort(names(parent.env(ns)))
[1] ".__C__CsparseMatrix" ".__C__dgCMatrix"     "setClass"


i.e., the imported classes are cached in the parent of the namespace (the
imports environment), and superclasses of dgCMatrix that are _not_ imported
are cached in the namespace itself.  The caching of superclasses does _not_
occur if I add all of the superclasses to the importClassesFrom directive
in NAMESPACE _or_ if I delete the call to setClass in R/*.R.

It is precisely these cached superclasses that are liable to become stale,
because, if I understand correctly, the namespace is populated and serialized
at _install_ time, whereas the imports environment is populated at _load_ time.

Hence by clarifying in WRE that packages should import exported superclasses
of classes that they extend, etc., we could stem some of the "staleness" on
CRAN ...

But maybe my analysis is mistaken, so I'll wait for comments from others ...

Mikael
package <- "TestPackage"
dir.create(file.path(package, "R"), recursive = TRUE)

cat(file = file.path(package, "DESCRIPTION"), "
Package: TestPackage
Version: 0.0-0
License: GPL (>= 2)
Description: A (one paragraph) description of what
  the package does and why it may be useful.
Title: My First Collection of Functions
Author: First Last [aut, cre]
Maintainer: First Last <first.l...@some.domain.net>
Imports: Matrix, methods
")

cat(file = file.path(package, "NAMESPACE"), "
export(zzz)
importFrom(methods, setClass)
importClassesFrom(Matrix, dgCMatrix, CsparseMatrix)
")

cat(file = file.path(package, "R", paste0(package, ".R")), "
zzz <- function() double(3L)
#setClass(\"whatever\", contains = \"dgCMatrix\")
")

tools:::Rcmd(c("build", package))
tools:::Rcmd(c("INSTALL", Sys.glob(paste0(package, "_*.tar.gz"))))

## unlink(Sys.glob(paste0(package, "*")), recursive = TRUE)
______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

Reply via email to