Dear John, Thanks for this. I'll give your new definition of isS4object() a try. The function is used in my Rcmdr package, which provides a basic-statistics GUI for R. When an object -- the result of executing a command -- is printed, I test whether it is an S4 object to decide whether to use show() or print().
Regards, John -------------------------------- John Fox Department of Sociology McMaster University Hamilton, Ontario Canada L8S 4M4 905-525-9140x23604 http://socserv.mcmaster.ca/jfox -------------------------------- > -----Original Message----- > From: [EMAIL PROTECTED] > [mailto:[EMAIL PROTECTED] On Behalf Of John Chambers > Sent: Saturday, December 11, 2004 11:41 AM > To: John Fox > Cc: 'Martin Maechler'; [EMAIL PROTECTED] > Subject: Re: [Rd] RE: [R] Testing for S4 objects > > > > John Fox wrote: > > Dear r-devel list members, > > > > I'm moving this question to r-devel because it seems > thornier than I > > originally thought. > > Yes, it's certainly not for r-help. > > > > > I've already mentioned (on r-help) that the approach that John > > Chambers suggested (below) fails for objects of class "by": > > > > > >>x <- rnorm(100) > >>y <- sample(2, 100, replace=TRUE) > >>res <- by(x, y, mean) > >>res > > > > INDICES: 1 > > [1] -0.03429679 > > ------------------------------------------------------------ > > INDICES: 2 > > [1] -0.1273790 > > > >>class(res) > > > > [1] "by" > > > >>isS4object <- function(object)(length(attr(object, "class"))==1 && > > > > + !is.null(getClass(class(object)))) > > > >>isS4object(res) > > > > Error in getClass(class(object)) : "by" is not a defined class > > > > > > I tried to fix that, but I've now discovered more general > problems; e.g.: > > Let's not revert to slotNames(). For the reasons I mentioned > it's inevitably going to produce a confusing definition. > > There are a couple of problems (aside from my having used > getClass() where I meant to use getClassDef() :-{): > - we need to handle S3 classes that have been registered with > S4 dispatch by calling setOldClass(). Doing this is strongly > recommended, but the effect is to create an S4 definition. > That's one reason why > lm() objects might appear to be S4 objects. Presumably, we > don't want that. > - eventually, if this is a serious thing that people need, we > need to worry about objects defined in namespaces, with > private class definitions. > > Here's a more careful version of the previous idea, which I > believe handles the first of these problems, by using the > fact that an object generated by new("foo",...) cannot come > from a VIRTUAL class. That gets actually to "What do we > really mean by an S4 object?" I'm essentially saying that an > object that could not have been created by a new() call is > not an S4 object. People could cheat, of course, and it's > not clear what we should do with such objects. Both the case > of no definition and the case of S3 classes registered with > setOldClass() should produce a VIRTUAL class. > > (By the way, I was wondering what the actual intent of this > function was. Usually, one would try to have generic > functions deal sensibly with objects for which they had no > method--either some default calculation or an error message. > The notion of "S4 object" is pretty general or vague, as > we're demonstrating. On the whole, it would be better not to > get tangled up in it.) > > I'm weakly confident that the current version also handles > the namespace issue, by using the actual class() call, which > should include a "package" attribute to get to the right namespace. > > But no assertions that extensive testing has been done. > Nevertheless, here is a second approximation. > > isS4Object <- function(object) { > if(length(attr(object, "class"))!= 1) > return(FALSE) > !isVirtualClass(getClass(class(object), TRUE)) } > > > > > > > > >>mod <- lm(y ~ x) > >>class(mod) > > > > [1] "lm" > > > >>isS4object(mod) > > > > [1] TRUE > > > >>class(summary(mod)) > > > > [1] "summary.lm" > > > >>isS4object(summary(mod)) > > > > Error in getClass(class(object)) : "summary.lm" is not a > defined class > > > > > > I've reverted to a modified version of my original proposal: > > > > > >>isS4object <- function(object) { > > > > + !(length(object) == 1 && class(object) == "character") && > > length(slotNames(object)) != 0 > > + } > > > >>isS4object(res) > > > > [1] FALSE > > > >>isS4object(mod) > > > > [1] FALSE > > > >>isS4object(summary(mod)) > > > > [1] FALSE > > > >># example from ?mle > >>x <- 0:10 > >>y <- c(26, 17, 13, 12, 20, 5, 9, 8, 5, 4, 8) ll <- > function(ymax=15, > >>xhalf=6) > > > > + -sum(stats::dpois(y, lambda=ymax/(1+x/xhalf), log=TRUE)) > > > >>fit <- mle(ll) > > > > Warning message: > > NaNs produced in: dpois(x, lambda, log) > > > >>isS4object(fit) > > > > [1] TRUE > > > >>isS4object("mle") > > > > [1] FALSE > > > > > > All this is with R 2.0.1 under Windows NT. > > > > Comments would be appreciated. > > > > John > > > > -------------------------------- > > John Fox > > Department of Sociology > > McMaster University > > Hamilton, Ontario > > Canada L8S 4M4 > > 905-525-9140x23604 > > http://socserv.mcmaster.ca/jfox > > -------------------------------- > > > > > >>-----Original Message----- > >>From: John Chambers [mailto:[EMAIL PROTECTED] > >>Sent: Tuesday, November 30, 2004 9:40 AM > >>To: John Fox > >>Cc: Martin Maechler; [EMAIL PROTECTED] > >>Subject: Re: [R] Testing for S4 objects > >> > >>Let me suggest a different test, because slotNames was > written to work > >>differently when given a string or a class definition. With your > >>definition, > >> > >>R> x <- "classRepresentation" > >>R> isS4object(x) > >>[1] TRUE > >> > >>which I assume is not what you wanted. (Given a single string, > >>slotNames() tries to look up the class definition of that name.) > >> > >>How about the following? The logic is that an S4 object > must have an > >>actual class attribute of length 1 (that rules out basic > data types, > >>where class(x) is a string but there is no actual > attribute, and also > >>rules out some S3 objects). Then if that's true, try to > look up the > >>class definition. If it is non-null, seems like an S4 object. > >> > >>R> isS4object <- function(object)(length(attr(object, > "class"))==1 && > >>+ !is.null(getClass(class(object)))) > >>R> isS4object(x) > >>[1] FALSE > >>R> isS4object(getClass(class(x))) > >>[1] TRUE > >> > >>This definition seems to work, at least on the examples I > could think > >>of right away. Notice though, that some classes, such as > "ts", that > >>have been around for a long while are nevertheless legitimate S4 > >>classes, so: > >> > >>R> t1 = ts(1:12) > >>R> isS4object(t1) > >>[1] TRUE > >> > >>(this applies to either version of isS4object). > >> > >>There are a couple of details, more appropriate for the > r-devel list. > >>Seems a good candidate for a function to add to R. > >> > >> > >>On Sat, 27 Nov 2004 17:48:30 -0500, John Fox > <[EMAIL PROTECTED]> wrote: > >> > >>>Dear Martin, > >>> > >>>As it turns out, the test that I proposed (i.e., testing for NULL > >>>slotNames) sometimes fails. For example: > >>> > >>> > >>>>library(car) > >>>>data(Prestige) > >>>>sum <- summary(lm(prestige ~ income + education, data=Prestige)) > >>>>slotNames(sum) > >>> > >>>character(0) > >>> > >>>The following, however, seems to work (at least as far as > I've been > >>>able to > >>>ascertain): > >>> > >>>isS4object <- function(object) length(slotNames(object)) != 0 > >>> > >>>I hope that this is a more robust test. > >>> > >>> > >>> > >>>John > >>> > >>>-------------------------------- > >>>John Fox > >>>Department of Sociology > >>>McMaster University > >>>Hamilton, Ontario > >>>Canada L8S 4M4 > >>>905-525-9140x23604 > >>>http://socserv.mcmaster.ca/jfox > >>>-------------------------------- > >>> > >>> > >>>>-----Original Message----- > >>>>From: Martin Maechler [mailto:[EMAIL PROTECTED] > >>>>Sent: Friday, November 26, 2004 3:18 AM > >>>>To: John Fox > >>>>Cc: [EMAIL PROTECTED] > >>>>Subject: Re: [R] Testing for S4 objects > >>>> > >>>> > >>>>>>>>>"JohnF" == John Fox <[EMAIL PROTECTED]> > >>>>>>>>> on Thu, 25 Nov 2004 22:28:50 -0500 writes: > >>>> > >>>> JohnF> Dear r-help list members, Is there a way to test > >>>> JohnF> whether an object is an S4 object? The best that I've > >>>> JohnF> been able to come up with is > >>>> > >>>> JohnF> isS4object <- function(object) > >>>>!(is.null(slotNames(object))) > >>>> > >>>>you can drop one pair of "(..)" to give > >>>> > >>>> isS4object <- function(object) !is.null(slotNames(object)) > >>>> > >>>> > >>>> JohnF> which assumes that an S4 object has at least one > >>>> JohnF> slot. I think this is safe, but perhaps I'm missing > >>>> JohnF> something. > >>>> > >>>>The question is a very good one -- that I have posed to R-core a > >>>>while ago myself. > >>>> > >>>>Inside utils:::str.default {which doesn't show the many > >> > >>commments > >> > >>>>in the *source* of str.default()}, I have wanted a way that even > >>>>works when the 'methods' package is not attached and use the more > >>>>obscure > >>>> > >>>> #NOT yet:if(has.class <- !is.null(cl <- class(object))) > >>>> if(has.class <- !is.null(cl <- attr(object, "class")))# > >>>>S3 or S4 class > >>>> S4 <- !is.null(attr(cl, "package"))## <<<'kludge' FIXME! > >>>> ##or length(methods::getSlots(cl)) > 0 > >>>> > >>>>For the time being, I'd keep your function, but I don't > >> > >>think we'd > >> > >>>>guarantee that it will remain the appropriate test in all > >> > >>future. > >> > >>>>But till then many things will have happened (if not all of them > >>>>;-). > >>>> > >>>>Martin Maechler, ETH Zurich > >>>> > >>> > >>>______________________________________________ > >>>[EMAIL PROTECTED] mailing list > >>>https://stat.ethz.ch/mailman/listinfo/r-help > >>>PLEASE do read the posting guide! > >>>http://www.R-project.org/posting-guide.html > >>> > > > > > > ______________________________________________ > > [EMAIL PROTECTED] mailing list > > https://stat.ethz.ch/mailman/listinfo/r-devel > > > > ______________________________________________ > [EMAIL PROTECTED] mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel ______________________________________________ [EMAIL PROTECTED] mailing list https://stat.ethz.ch/mailman/listinfo/r-devel