From jmc at research.bell-labs.com  Thu Sep  9 17:41:33 2004
From: jmc at research.bell-labs.com (John Chambers)
Date: Thu Sep  9 17:41:51 2004
Subject: [Rd] as(object,"list")  as(object,"matrix") differences?
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>
	<200409091557360623.0F3F7FD6@mail.math.fu-berlin.de>
Message-ID: <414079AD.A9307DF6@research.bell-labs.com>

If the only issue is whether as(x, "list") preserves the names
attribute, this is certainly an easy change to implement, if the R
community decides that's the better solution.

With the release of 2.0 only a few weeks away, there's not much chance
of resolving the question for that version.  Although the change is
simple, there may be some implications that will not arise until a good
deal of testing is done.  So a more likely target is to resolve the
question for version 2.1.

By the way, one argument in your favor is that S-Plus retains the names
in as(x, "list") (but not in as(x, "numeric"), even if x had names in
that case).  So a closer approximation to compatibility with the
behavior of S-Plus would retain names.  (I'm not quite convinced this is
what the discussion in the green book would imply, but it's what
happens!)

If others have opinions, it would be good to hear them.

Meanwhile, a candidate for the simplest workaround:  Have new classes
extend the class "listNamed" defined below, rather than "list" directly,
and as(x, "list") should retain names, I think.

---------------------------------------------
setClass("listNamed", "list")

setAs("listNamed", "list", function(from) {
    if(strict) class(from) <- "list"
    from
})
---------------------------------------------

Although not necessary for correctness, it's probably good to add the
following method for "show".  (With the default method, names are not
printed, even though they are there--users are likely to be confused.)

---------------------------------------------
setMethod("show", "listNamed",
          function(object) {
              cat("An object of class ", class(object), "\n", sep="")
              show(as(object, "list"))
          })
---------------------------------------------

(By the way, the workaround depends on the bug fix to setAs committed
recently to r-devel, so if you try this you should use the latest
version.)

Wolski wrote:
> 
> 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

-- 
John M. Chambers                  jmc@bell-labs.com
Bell Labs, Lucent Technologies    office: (908)582-2681
700 Mountain Avenue, Room 2C-282  fax:    (908)582-3340
Murray Hill, NJ  07974            web: http://www.cs.bell-labs.com/~jmc


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