From wolski at molgen.mpg.de  Thu Sep  9 15:57:36 2004
From: wolski at molgen.mpg.de (Wolski)
Date: Thu Sep  9 15:57:45 2004
Subject: [Rd] as(object,"list")  as(object,"matrix") differences?
In-Reply-To: <413F12EB.5F76BBA5@research.bell-labs.com>
References: <200409071617210704.0504144D@mail.math.fu-berlin.de>
	<413DD80C.2D5EA9C9@research.bell-labs.com>
	<200409081219020786.0B1B546F@mail.math.fu-berlin.de>
	<413F12EB.5F76BBA5@research.bell-labs.com>
Message-ID: <200409091557360623.0F3F7FD6@mail.math.fu-berlin.de>

Hi!

First of all thanks a lot to John Chambers.  I think S4 makes some tasks really easier. 
This mail tries to summarise the mail exchange concerning contains="list" in S4.
I do not know all the R "internals" so instead of talking I try to use and to play around with S4. People like I learn by example. But I would like to use all features of S4. I dont say that anything is good or bad. I just ask on which parts and features can I rely on? About which parts of methods I be sure that there are not going to change in the nearest future? And making a search on several hundred packages in the lib directory, and finding that setAs is used only in the file methods/R-ex/as.R its not reassuring.

I like to use S4 and i like to use lists.

I like to use lists like maps or multimaps with key value pairs. I believe that I am not the only one who uses lists to store different types of objects and to access them using mylist[["key"]]. So in my opinion list had have and should have names. (I am not a phyton user yet but I know that phyton has also a data structure to store key value pairs and it is a quite important one.)

R provides a lot of powerfull functions which are operating on "lists" like sapply, lapply, mapply, [[]] [] etc.... 
And all the list methods lapply, [], etc preserve the list names. So if they "return a type" are "list" then list have names.  But as I said i understand examples and so probably nothing new to what you have already said. And I think that my examples will show that even in S4 except for the function as(object,"list") old style "list" have names attribute.

If I write a new class, and this class is a mainly a container class, I would like rather inherit from a list (contains="list") with names rather then include it (include means representation(list="list") like e.g. class Biobase:container does). I like to inherit because I would not like to wrap every possible list function which is available for lists. Its just because I even not know all of them. And if I have inheritance as a tool this is not neceassary. Any function working on lists can be used on a class inheriting from list.

The following code summarizes, by example, how names are treated when "list" is "contained" by a class. 
I show 3 versions how to inherit from "list" showing the problems with the 'naive' inheritance.
And I think that the example shows also that in S4 the old styl "list" class are with "names"! 
There are also some inconsistencies, bugs which I am going to show on occasion?



#NAIVE inheritance from list.
#define cass
setClass("ListWithNames","list")
setClass("Mlist"
         ,representation(info="character") #uniq names have to be unique?
         ,contains="ListWithNames"
         ,prototype(uniq=FALSE)
         )
         
tmp <- as.list(1:4)
names(tmp) <- letters[1:4]
mylist<-new("Mlist" , tmp , info="numeric" )

#Example of manipulating the list part of the object. 
as(mylist,"list")<-lapply(mylist,"+",3)
as(mylist,"list") <- mylist[2:4]

as(mylist,"list") <- as(mylist,"ListWithNames")[2:4]


#what does not work is assigning shorter lists without names. Seems like a bug. Or is there an explanation.
as(mylist,"list")<-as.list(1:5)
as(mylist,"list")<-as.list(1:4)

class(Mlist)
#I have not defined in class Representation 
# a names attribute but there is the name attribute anyway inherited by from list.

mylist@names

# But this does not work. Of course.
mylist@names <- letters[5:9]

#Slots are implemented using attributes?

attributes(mylist@.Data)$names #this is what is expected.
attributes(mylist)$names #But whats this?
attributes(mylist)$names <- letters[2:11]  
attributes(mylist@.Data)$names #are they the same? synchronized?

# So if @names are there why not make it official ?
# I make it official with a new class definition.
# REFINED version of "list" inheritance.

setClass("MlistN"
         ,representation(info="character",names="character") #uniq names have to be unique?
         ,contains="ListWithNames"
         )

mylistNam<-new("MlistN" , tmp , info="numeric")
mylistNam@names<-letters[4:7]
mylistNam["d"]
mylistNam[["d"]]

as(mylistNam,"list")<-tmp[1:3]

as(mylistNam,"list")<-as.list(1:4) 
as(mylistNam,"list")<-as.list(1:3) #<- the same error as before.
as(mylistNam,"list")<-list(a=1,b=2,c=3,d=4)

#to get it more complicated
as(mylistNam,"ListWithNames") # Is without names??

## MORE REFINED version of list inheritance.
setClass("MlistN"
         ,representation(info="character",names="character") #uniq names have to be unique?
         ,contains="list"
         )

# I dont like the as(o,"list") 
# My Solution. Now it does not mether wheter the list has or has not names is longer or shorter.

setAs("MlistN","list"
	,def=function(from){
		print("test")
		to<-from@.Data
		names(to)<-from@names
		to
	}
	,replace=function(from,value)
	{
		from@.Data<-value
		from@names<-names(value)
		from	
	}
 )


bublegum <- list(b=1, u=3, b=4, l=4, e=2, g=1, u=4, m=2)
mylistNam <- bublegum
bubl<-bublegum[1:4]
names(bubl)<-NULL
as(mylistNam,"list") <- bubl

I have just one question: Can I rely that this is not going to change in further versions of R? 

/E


[Rd] as(object,"list") as(object,"matrix") differences?
Wolski