Hi,

Thanks to all of you for helpfull sugestions.


This weekend I found a manuscript by R. Gentlemen which discussed similar topics:
http://www.stat.auckland.ac.nz/S-Workshop/Gentleman/container.pdf



Yours,





John Chambers wrote:

Eric Lecoutre wrote:


Hi,

For your lm problem, you could begin to create a virtual class that accepts
either NULL or a lm object:

> setClassUnion("mylm", c("NULL","lm"))
> setClass("foo", representation(x="numeric", y="mylm"))
> new("foo",x=1,y=NULL)

Then, you have to check the content of slot y in any function that will
manipulate objects of class "foo":

setMethod("show","foo",function(object)
{
cat("\n object of class foo")
if (!is.null([EMAIL PROTECTED])) cat(" does have a lm object in slot y!")
})



This is OK, but it illustrates why it would _not_ be a good idea to allow NULL values automatically for an arbitrary class. The implementation here says that the "y" slot can be either a NULL or an "lm" object. That is a different statement from saying that "y" must be an "lm" object.

Either approach could make sense.  But what one really wants (in any
definiton of a new class) is to match the actual definition to the
intended meaning.

With your suggestion, the designer of class "foo" is basically passing
on to the implenters of methods the responsibility to check for a NULL
"y" slot.  If it makes sense for legitimate "foo" objects to exist that
have a NULL "y" slot, then that extra work is part of the design of the
"foo" class.  Your definition of the class essentially says that the
"lm" model is an optional part of the object.

But if in fact it _only_ makes sense for the object to have a true
model, then one should not define a class that conflicts with the
intended meaning.   There was no indication in the initial question that
NULL made sense.  If we're just introducing the NULL possibility as a
programming hack, that's not really a good idea.

The other approach is to insist that the computations creating a "foo"
object generate a valid "lm" object, if the user didn't supply one. Then methods for "foo" objects are not required to check. One way to
make the stricter approach work would be to have a method for
initialize() for class "foo" that generated a model from the other slots
in the object.


For example, the class might represent "x" and "y" data, and a model
that by default was the linear model for y~x.  Something like the
following would implement that idea:

setClass("withLm", representation(x="numeric", y="numeric", model =
"lm"))

setMethod("initialize", "withLm",
         function(.Object, x = numeric(), y = numeric(), model = NULL)
{
             if(is.null(model))
                 model <- lm(y ~ x)
             callNextMethod(.Object, x=x, y=y, model=model)
         }
         )



(unfortunately, lm() does not allow fitting vectors of length 0, so if
this were a real example there are a few boundary cases to consider ;-)




Eric

At 14:35 30/09/2004, Witold Eryk Wolski wrote:


Hi,

But "any" rises some other problems well known from S3. One has "any" for
"free" in S3. You don't need S4. . But I know how "if" polluted
functions  look like in S3. They are hard to understand and  to maintain.
Hence I am quite happy to use S4.
Type-checking is usefull if you program with data. Also if you are on the
"C side" of the object. A further problem which I have with "any" is, that
lm="any" in setClass tells you exactly ANYthing (and you are back in S3).
And thats not what I like.*
Hence, I do not want to use any in this case.

I think that allowing to assing NULL to a slot will solve some problems
which I have with S4 so far.

a) How to express that an a slot content was not assigned so far? J.C.
suggest to use character(0), lm(1~1) etc. The problem I have with
insterting lm(1~1) in slot mod in my class Ctest are that I have 100000
instances of object Ctest. At initialization everyone contains an object
lm(1~1). But please  note the following.



x<-lm(1~1)
object.size(x)


[1] 6388


object.size(NULL)


[1] 0

Unfortunately S4 do not have references. Hence, I can not store a
reference to a single instance of lm(1~1) .

Exactly the same problems I have if I want to "delete" an object. For
example you like to have a slot  which stores some data which is important
if the object is in one state. But if the state of the object changes you
do not need that data anymore. Hence, you would like to delete it to get
storage.  You can only do it if you have like you suggest "any", but the
consequence is "if" polluted code, or using slot(obj,"mod",check=FALSE)<- NULL.

But the documentation for slot states.
check: " You should never set this to 'FALSE' in normal
        use, since the result can create invalid objects. "


b) The Problem which I have writing intitialization functions like suggested by J.C is: Imagine you have an object with twenty slots. You have to write and initialize function with approximately 20 "if"'s. One of the contribution of S4, as mentioned above, is to help you to avoid writing such "if" polluted functions. But as I sometimes forget any role has it's exceptions. So I can live with one function looking ugly in S4 instead of having all functions "if" polluted like in case of S3. The only consequence so far is that I try to avoid to write initialize functions. I do it only in some rare very special cases.

The NULL exception in slot assignement will allow me object initialization
using just "new" without providing a "if" polluted function initialize.



setClass("bar")


[1] "bar"


setClass("foo", representation(x="numeric", y="bar"))


[1] "foo"


new("foo", x=1)


Error in validObject(.Object) : Invalid "foo" object: Invalid object for
slot "y" in class "foo": got class "NULL", should be or extend class "bar"


Are there S4 inherent solutions to this questions?


Yours. /E

*(I would rather compare "any" to the Object class then to null in java.
It has a different function.)

Pfaff, Bernhard wrote:



Hi,

Thanks a lot for pointing me to setOldClass().

What is exactly the point against it, to allow NULL to be a special case
which can be assigned to any slot? I think in java one can assing null
to any slot (I do not like java but not because of that).
I am asking because for some objects it may be hard to define something
equivalent to numeric(0). And even lm(1~1) is not that what I am looking
for. I would like to have the case
of an unassigned slot (Just think about storage?) even to the expense
checking every time if the slot is not null.



Hello Eryk,

how about "ANY" and checking where suitable/needed if the passed object for
"mod" is of class "lm" at a later stage in your code, like in:

setClass("Ctest"
       ,representation(
               test="character"
               ,bla="character"
               ,mod="ANY"              )
       )

test1 <- new("Ctest",mod=lm(1~1))
is([EMAIL PROTECTED], "lm")

test2 <- new("Ctest",test="bla")
is([EMAIL PROTECTED], "lm")

test3 <- new("Ctest",bla="brum")
is([EMAIL PROTECTED], "lm")

test4 <- new("Ctest",test="bla",bla="brum")
is([EMAIL PROTECTED], "lm")

From there on you could use stop() or warning() or whatever you want to
return to the user as information which class mod should belong to.

HTH,
Bernhard



______________________________________________
[EMAIL PROTECTED] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Eric Lecoutre
UCL /  Institut de Statistique
Voie du Roman Pays, 20
1348 Louvain-la-Neuve
Belgium

tel: (+32)(0)10473050
[EMAIL PROTECTED]
http://www.stat.ucl.ac.be/ISpersonnel/lecoutre

If the statistics are boring, then you've got the wrong numbers. -Edward
Tufte

______________________________________________
[EMAIL PROTECTED] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel







--
Dipl. bio-chem. Witold Eryk Wolski MPI-Moleculare Genetic
Ihnestrasse 63-73 14195 Berlin _
tel: 0049-30-83875219 __("< 'v'
http://www.molgen.mpg.de/~wolski \__/ / \
mail: [EMAIL PROTECTED] ^^ w w
[EMAIL PROTECTED]


______________________________________________
[EMAIL PROTECTED] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

Reply via email to