From mtmorgan at fhcrc.org  Wed May 23 20:00:37 2007
From: mtmorgan at fhcrc.org (Martin Morgan)
Date: Wed, 23 May 2007 11:00:37 -0700
Subject: [Rd] list element names in S4 class extending list
In-Reply-To: <Pine.GSO.4.58.0705211308340.15906@capecod.bwh.harvard.edu>
	(Vincent
	Carey's message of "Mon, 21 May 2007 13:12:54 -0400 (EDT)")
References: <Pine.GSO.4.58.0705211308340.15906@capecod.bwh.harvard.edu>
Message-ID: <6phveejzagq.fsf@gopher4.fhcrc.org>

Hi Vince --

Not a solution, but a little understanding and a workaround. With C1,
what happens is that the 'names' attribute of ll gets transfered to
the 'names' attribute of the S4 instance.

> setClass("C1", contains="list")
[1] "C1"
> setClass("C2", contains="C1")
[1] "C2"
> ll <- list(a=1, b=2)
> c1 <- new("C1", ll)
> names(c1)
[1] "a" "b"
> names(c1 at .Data)
NULL

With C2, the action happens in the constructed method coerce<-("C2",
"list") (available after class instantiation from the list):

> setClass("C1", contains="list")
[1] "C1"
> setClass("C2", contains="C1")
[1] "C2"
> ll <- list(a=1, b=2)
> c2 <- new("C2", ll)
> getMethod("coerce<-", c("C2", "list"))
Method Definition:

function (from, to, value) 
{
    .value <- as(from, "C1")
    as(.value, "list") <- value
    value <- .value
    {
        for (what in ".Data") slot(from, what) <- slot(value, 
            what)
        from
    }
}

Signatures:
        from to    
target  "C2" "list"
defined "C2" "list"

C2 gets coerced to its super class, C1. C1 is then assigned the list,
including attributes. The bug enters in the 'for (what in ".Data")',
where the slots of .Data from C1, but not the attributes,  are
copied.

The code chunk above is generated in methods:::.simpleReplaceExpr;
naively copying attributes from 'value' to 'from' does not work, as
attributes on 'from' include it's class.

A workaround would be to define an appropriate setAs

> setClass("C1", contains="list")
[1] "C1"
> setClass("C2", contains="C1")
[1] "C2"
> setAs("C2", "list",
+       def=function(from) stop('your def here'),
+       replace=function(from, to, value) {
+           from at .Data <- value
+           from
+       })
[1] "coerce<-"
> ll <- list(a=1, b=2)
> c2 <- new("C2", ll)
> names(c2)
[1] "a" "b"
> names(c2 at .Data)
NULL

presumably this breaks under more esoteric scenarios.

Martin

Vincent Carey 525-2265 <stvjc at channing.harvard.edu> writes:

> can list names attributes be preserved through S4
> class containment?  seems to be so but only if the containment
> relationship is direct ... see below.
>
>> setClass("c1", contains="list")
> [1] "c1"
>> l1 = list(a=1, b=2)
>> o1 = new("c1", l1)
>> names(o1)     # pleasant surprise
> [1] "a" "b"
>> setClass("c2", contains="c1")
> [1] "c2"
>> o2 = new("c2", l1)
>> names(o2)     # sad
> NULL
>> sessionInfo()
> R version 2.6.0 Under development (unstable) (2007-05-11 r41535)
> powerpc-apple-darwin8.9.0
>
> locale:
> C
>
> attached base packages:
> [1] "stats"     "graphics"  "grDevices" "utils"     "datasets"  "methods"
> [7] "base"
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel

-- 
Martin Morgan
Bioconductor / Computational Biology
http://bioconductor.org



[Rd] list element names in S4 class extending list
Martin Morgan