From martin.kober at gmail.com  Wed Sep 16 02:23:24 2009
From: martin.kober at gmail.com (Martin Kober)
Date: Wed, 16 Sep 2009 02:23:24 +0200
Subject: [Rd] S3 objects in S4 slots
In-Reply-To: <4AAFBA9C.5090502@r-project.org>
References: <116117690909150300v4a703807se7b08b94c3f1a68d@mail.gmail.com>
	<4AAF956B.7090704@fhcrc.org> <4AAFBA9C.5090502@r-project.org>
Message-ID: <116117690909151723o466d0f9eh772f3d6dbffd7e90@mail.gmail.com>

2009/9/15 John Chambers <jmc at r-project.org>:
> I'll look at this in more detail (though not for a few days), but the
> essence I think is that nothing in the current version allows one to say the
> S3 equivalent of
>
> setClass("VCorpus", contains = "list", ....)
>
> Seems a (minor, I hope) glitch that what Martin K.? tried didn't work:
> ?? setOldClass(c("VCorpus", "Corpus", "list"))
>
> As far as I can see, setOldClass() should understand the basic data types as
> valid superclasses.
That would be really useful.

Do you think it would be feasible to automatically assume that all S3
objects "contain" their basic data type (like a list, in this case)
for purposes of S4 class matching, when no other information is given?

At least in this specific case, the idea is that corpus objects can be
used as a list of character vectors and code does not need to know
anything about the object structure as long as only the contents of
the list are needed. So (again, in this specific case), I would
consider "defaulting" to the underlying data type optimal.

>
> Martin Morgan's code is indeed a workaround.? And as Martin Maechler
> commented, the intention is to make S3 and S4 classes play together as much
> as possible.
>

Thanks to Martin Morgan for the workaround, it works very well.

>
> Morgan wrote:
>
> Hi Martin Kober --
> Martin Kober wrote:
>
>
> Hello,
> I am the maintainer of the stringkernels package and have come across
> a problem with using S3 objects in my S4 classes.
> Specifically, I have an S4 class with a slot that takes a text corpus
> as a list of character vectors. tm (version 0.5) saves corpora as
> lists with a class attribute of c("VCorpus", "Corpus", "list"). I
> don't actually need the class-specific attributes, I only care about
> the list itself.
> Here's a simplified example of my problem:
>
>
> setClass("testclass", representation(slot="list"))
>
>
> [1] "testclass"
>
>
> a = list(a="1", b="2")
> class(a) = c("VCorpus", "Corpus", "list") # same as corpora in tm v0.5
>
>
> This has the feel of a workaround, but
> setOldClass(class(a)[1:2]); setIs("Corpus", "list")
> helps here, first registering c('vCorpus', 'Corpus') as an S3 hierarchy
> and then defining the relationship between the root of the hierarchy and
> (the S4 class) 'list'.
> Martin (Morgan)
>
>
> x = new("testclass", slot=a)
>
>
> Error in validObject(.Object) :
>   invalid class "testclass" object: 1: invalid object for slot "slot"
> in class "testclass": got class "VCorpus", should be or extend class
> "list"
> invalid class "testclass" object: 2: invalid object for slot "slot" in
> class "testclass": got class "Corpus", should be or extend class
> "list"
> invalid class "testclass" object: 3: invalid object for slot "slot" in
> class "testclass": got class "list", should be or extend class "list"
> The last line is a bit confusing here (``got class "list", should be
> or extend class "list"''). There's an even more confusing error
> message when I try to assign the slot later on:
>
>
> y = new("testclass")
> y at slot = a
>
>
> Error in checkSlotAssignment(object, name, value) :
>   c("assignment of an object of class \"VCorpus\" is not valid for
> slot \"slot\" in an object of class \"testclass\"; is(value, \"list\")
> is not TRUE", "assignment of an object of class \"Corpus\" is not
> valid for slot \"slot\" in an object of class \"testclass\"; is(value,
> \"list\") is not TRUE", "assignment of an object of class \"list\" is
> not valid for slot \"slot\" in an object of class \"testclass\";
> is(value, \"list\") is not TRUE")
> The last part of the message claims that ``is(value, "list") is not
> TRUE'', but is(a, "list") is certainly TRUE. (??)
> On a side note, it does work when "list" is the first entry in class().
> I tried to use setOldClass, but seemingly using list is not possible
> because it does not extend oldClass, or I didn't find out how to do
> it:
>
>
> setOldClass(c("VCorpus", "Corpus", "list"))
>
>
> Error in setOldClass(c("VCorpus", "Corpus", "list")) :
>   inconsistent old-style class information for "list"; the class is
> defined but does not extend "oldClass"
> Intuitively I would have thought that, because the underlying data is
> of type list, it would "fit" into an object slot requiring a list,
> irrespective of S3 class attributes. The only thing I can think of is
> a manual solution removing the class attribute.
> Is there a way to define lists with S3 class attributes such that they
> are accepted as lists in S4 object slots? Or any other ways to solve
> this?
> Thanks in advance
> Best Regards
> Martin
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>



[Rd] S3 objects in S4 slots
Martin Kober