[Bioc-devel] Extend class definition on attaching a package

Martin Morgan mtmorgan at fhcrc.org
Fri Aug 27 18:22:36 CEST 2010


On 08/26/2010 05:58 PM, Venkatraman Seshan wrote:
> Thanks Martin.  I was probably making it more complicated than it needed to
> be.  I just want to load bigmemory package (if it is installed) and redefine
> the classes. I followed your advice and now AllClasses.R is
> 
> setClassUnion("mymatrix", c("mymatrix"))
> setClass("mydata", representation(x="numeric", y="cnmatrix"))
> 
> and zzz.R is
> 
> .onLoad <- function(libname, pkgname) {
>   bigmem <-
> suppressWarnings(suppressPackageStartupMessages(require(bigmemory)))
>   if (bigmem) {
>     setClassUnion("cnmatrix", c("matrix", "big.matrix"))
>     setClass("mydata", representation(x="numeric", y="cnmatrix"))
>   }}
> 
> Now it seems to work but I get the following warning message both on R CMD
> check and loading the package within R
> 
> Class "big.matrix" is defined (with package slot bigmemory) but no metadata
> object found to revise superClass information---not exported?  Making a copy
> in package foo
> 
> I assume it is because NAMESPACE doesn't have importClasseFrom(bigmemory,
> big.matrix)
> 
> Is there a way I can change the NAMESPACE (in .onLoad or elsewhere)?

I guess you're trying to develop a package that has functionality that
has code that is conditional on the bigmemory package -- if bigmemory is
available then do one thing, otherwise do another. But this is not, in
my opinion, a good idea -- your user gets different behavior on Monday
versus Wednesday (because they installed bigmemory on Tuesday) and you
have two code branches to maintain (which leads to headaches, as
evidenced by this thread!). So I think you really just want to

  Imports: bigmemmory

in your DESCRIPTION file,

importClassesFrom(bigmemory, big.matrix)

in NAMESPACE

and

setClassUnion("cnmatrix", c("matrix", "big.matrix"))
setClass("mydata",
         representation=representation(x="numeric", y="cnmatrix"))

in the 'top level' (i.e., not in .onLoad or other function call) of some
R/*R file.

Actually my stronger advice is that you avoid the setClassUnion --
you're really saying that your 'cnmatrix' walks and talks exactly like a
matrix and a big.matrix, and vice versa, when really you have no control
over what methods are defined for matrix or big.matrix (any package can
define methods for these classes) so you have no idea whether the
methods are appropriate for cnmatrix. Better in my opinion to implement
the interface that is directly relevant to cnmatrix, even if it is often
simple delegation to a 'matrix' slot of cnmatrix.

Martin


> 
> Thanks again,
> Venkat
> 
> 
> On Thu, Aug 26, 2010 at 7:58 PM, Martin Morgan <mtmorgan at fhcrc.org> wrote:
> 
>> On 08/26/2010 12:58 PM, Venkatraman Seshan wrote:
>>> In AllClasses.R I used
>>>
>>> setClassUnion("cnmatrix", c("matrix"))
>>>
>>> Sorry for the typo.
>>>
>>> Venkat
>>>
>>> On Thu, Aug 26, 2010 at 3:31 PM, Venkatraman Seshan <veseshan at gmail.com
>>> wrote:
>>>
>>>> Can the class definition in package "foo" be changed after the package
>> is
>>>> attached?  I am trying to do the following.
>>>>
>>>> The AllClasses.R file has the following class definitions.
>>>>
>>>> setClassUnion("mymatrix", c("mymatrix"))
>>>> setClass("mydata", representation(x="numeric", y="cnmatrix"))
>>>>
>>>> In zzz.R the .onLoad has the following:
>>>>
>>>>   setHook(packageEvent("bigmemory", "attach"),
>>>>           function(...){
>>>>             setIs("big.matrix", "cnmatrix")
>>>>             setClass("mydata", representation(x="numeric", y="cnmatrix")
>>>>           })
>>>>
>>>> When I now do R CMD check pkg it is completed but I get a note
>>>>
>>>> * checking R code for possible problems ... NOTE
>>>> Error in setIs("big.matrix", "cnmatrix") :
>>>>   cannot create a 'setIs' relation when neither of the classes
>>>> ("big.matrix" and "cnmatrix") is local and modifiable in this package
>>>>
>>>> How do I modify the definition of a class in a package?
>>
>> Hi Venkat -- not really answering your question, but I don't really
>> think you want to do either setClassUnion or setIs -- inheritance is
>> difficult enough to understand without adding novel relationships
>> between classes. And I don't think you really want to conditionally
>> define class relationships on package load either (which I is guess what
>> setHook(packageEvent()) accomplishes; I've never seen that before);
>> these all sound like you're making trouble for yourself (and users of
>> your package) in the future.
>>
>> But...
>>
>> .onLoad is run after Import: and Depend: packages have been loaded, and
>> before the name space of the package in which .onLoad is defined is
>> 'sealed'. I think this means that if you had Import'ed or Depend'ed on
>> bigmemory, then a setIs and setClass in .onLoad (not setHook(...)) would
>> be successful, just as
>>
>>> library(bigmemory)
>>> setClassUnion("cnmatrix", "matrix")
>> [1] "cnmatrix"
>>> setIs("big.matrix", "cnmatrix")
>>> setClass("mydata", representation(x="numeric", y="cnmatrix"))
>> [1] "mydata"
>>
>> are successful when run in an R session.
>>
>> So I guess what happens is the 'packageEvent' isn't actually evaluated
>> in .onLoad, but afterward, when bigmemory is loaded (by some other code
>> in your package? I'm not understanding how R CMD check is detecting the
>> error) and your name space has already been sealed (which occurs after
>> the .onLoad hook runs) and is therefore not modifiable. Maybe you could
>> create an environment in your package
>>
>>  .secrets <- new.env(parent=emptyenv())
>>  setPackageName("MyPackage", .secrets)
>>
>> and place your class definition there
>>
>>  setClass("cnmatrix", where=.secrets)
>>
>> .secrets isn't sealed, so the class definition might still be
>> modifiable. I really don't know how this would work, e.g., exporting
>> cnmatrix from your package name space, invoking methods, etc., or
>> whether it would provide a way to modify the class definition once the
>> name space is sealed. My little experiments suggest that you can create
>> an instance with
>>
>>  new(getClassDef("cnmatrix", where=MyPackage:::.secrets))
>>
>> or by
>>
>>  attach(MyPackage:::.secrets, name="search")
>>  new("MyClass")
>>
>> and create a setIs relationship, without generating errors or warnings,
>> with
>>
>>  attach(MyPackage:::.secrets, name="secrets")
>>  setIs("big.matrix", "cnmatrix", where="secrets")
>>  detach("secrets")
>>
>> but all of this seems like a big hack.
>>
>> Martin
>>
>>>>
>>>> Thanks,
>>>> Venkat
>>>>
>>>> My R.Version()
>>>> $platform
>>>> [1] "x86_64-pc-linux-gnu"
>>>>
>>>> $arch
>>>> [1] "x86_64"
>>>>
>>>> $os
>>>> [1] "linux-gnu"
>>>>
>>>> $system
>>>> [1] "x86_64, linux-gnu"
>>>>
>>>> $status
>>>> [1] ""
>>>>
>>>> $major
>>>> [1] "2"
>>>>
>>>> $minor
>>>> [1] "11.1"
>>>>
>>>> $year
>>>> [1] "2010"
>>>>
>>>> $month
>>>> [1] "05"
>>>>
>>>> $day
>>>> [1] "31"
>>>>
>>>> $`svn rev`
>>>> [1] "52157"
>>>>
>>>> $language
>>>> [1] "R"
>>>>
>>>> $version.string
>>>> [1] "R version 2.11.1 (2010-05-31)"
>>>>
>>>>
>>>
>>>       [[alternative HTML version deleted]]
>>>
>>> _______________________________________________
>>> Bioc-devel at stat.math.ethz.ch mailing list
>>> https://stat.ethz.ch/mailman/listinfo/bioc-devel
>>
>>
>> --
>> Martin Morgan
>> Computational Biology / Fred Hutchinson Cancer Research Center
>> 1100 Fairview Ave. N.
>> PO Box 19024 Seattle, WA 98109
>>
>> Location: Arnold Building M1 B861
>> Phone: (206) 667-2793
>>
> 


-- 
Martin Morgan
Computational Biology / Fred Hutchinson Cancer Research Center
1100 Fairview Ave. N.
PO Box 19024 Seattle, WA 98109

Location: Arnold Building M1 B861
Phone: (206) 667-2793



More information about the Bioc-devel mailing list