From baud-bovy.gabriel at hsr.it  Tue May 10 13:46:52 2005
From: baud-bovy.gabriel at hsr.it (Gabriel Baud-Bovy)
Date: Tue May 10 14:08:12 2005
Subject: [Rd] Implementation of the names attribute of attribute lists 
Message-ID: <5.2.1.1.0.20050510124327.02b0d900@mail.hsr.it>

Dear all,

Internally, the attribute list appears to be implemented as an generic
list vector with a names attributes (i.e., the attribute slot in the object's
SEXPREC structure would point toward a VECTOR_SEXPREC representing
a generic vector).

 > attributes(c(a=1))
$names
[1] "a"
 > typeof(attributes(c(a=1)))
[1] "list"

 From R, it appears as if the named list had itself an
named attributes list and so on .... until no end

 > attributes(attributes(c(a=1)))
$names
[1] "names"
 > attributes(attributes(attributes(c(a=1))))
$names
[1] "names"

Etc.

This is also the case for any object  having an attributes list.

 > attributes(matrix(1,1,1))
$dim
[1] 1 1
 > attributes(attributes(matrix(1,1,1)))
$names
[1] "dim"
 > attributes(attributes(attributes(matrix(1,1,1))))
$names
[1] "names"

Obviously, this behavior of the attributes function cannot reflect the
actual internal structure of the object.  My question is therefore
whether named lists used as attribute have themselves a names attribute?
Another possibility would be that the names attribute of an attribute list
does not have a names attribute. A final possibility might be that
attribute list are implemented with dotted lists (pairlists) and
that the behaviour attributes reflect pairlist's "virtual" names
attributes. In this case, however, one would have expected

typeof(attributes(attributes(c(a=1))))
[1] "list"

to return "pairlist".

Could you reply to me on my private address? Thank you a lot.

Gabriel

PS: I wrote a function that prints the list-like internal structure
of any R object (this is quite easy indeed  :-)) and wrote the draft
of an article documenting it that I am thinking of submitting to
R-news. I would however appreciate your feedback on it (did I reinvent
the wheel?). This function, I think, could be used in many places
to document apparently obscure or confusing aspects of the R
language to a non-expert user. It is also quite useful when "computing
on the language".

## The print.object function prints a tree representing the list-like structure
## of any R object
##
## x: any R object
## typefun: anfunction returning the object's type (e.g., mode, 
storage.mode, class)
## print.attributes: flag indicating whether to print or not the attributes 
list
## deparse.level: the printout beyond this level is produced by the deparse 
function
##
## The name and level arguments are not intended to be used at the user-level.
print.object<-function(x,typefun=typeof,print.attributes=F,deparse.level=Inf,name=NULL,level=0) 
{
         margin<-paste(rep("  ",level),collapse="")
         # tag contain the name of the object (if any)
         tag<-if(!is.null(name)) paste("[",name,"] ",sep="") else ""
         #
         if(level>=deparse.level) {
                 # if level exceeds maximum, simplify output by using 
deparse function
                 cat(margin,"+ ",tag,"deparse : 
",paste(deparse(x),collapse=""),"\n",sep="")
         } else if(is.element(typeof(x),c("environment","promise"))) {
                 # environment and promises are recusive objects that 
cannot be transformed
                 # into list
                 cat(margin,"+ ",tag,"<",typefun(x),">=",sep="")
                 print(x)
         } else if(typeof(x)=="closure") {
                 cat(margin,"+ ",tag,"<",typefun(x),">\n",sep="")
                 # print each part (formals, body and environment) of a 
function object separately
                 print.object(formals(x),typefun,print.attributes,deparse.level,"[formals]",level+1)
                 print.object(body(x),typefun,print.attributes,deparse.level,"[body]",level+1)
                 print.object(environment(x),typefun,print.attributes,deparse.level,"[env]",level+1) 

         } else if(is.recursive(x)) {
                 # print type of the recursive object (as determined by 
typefun function)
                 cat(margin,"+ ",tag,"<",typefun(x),">\n",sep="")
                 # loop to print each element of the recursive object
                 # note: element's name is transmitted separetely (NULL if 
absent)
                 xx<-as.list(x)
                 for(i in seq(along=xx)) 
print.object(xx[[i]],typefun,print.attributes,deparse.level,names(xx)[i],level+1)
         } else {
                 # print atomic objects (vector, matrices, etc)
                 aux<-switch(as.character(mode(x)),
                         "character"=paste("\'",x,"\'",sep=""), # add 
quotes to characters
                         "NULL"="NULL",
                         as.character(x))
                 aux<-paste(aux,collapse=",")
                 if(nchar(aux)==0)aux<-"\'\'" # occurs in case of formals 
without default value in a function definition
                 cat(margin,"- ",tag,"<", typefun(x),">=",aux,sep="")
                 # names are also printed if they exist
                 if(!is.null(names(x))) cat(" [names]=", 
paste("\'",names(x),"\'",sep="",collapse=","),sep="")
                 cat("\n")
         }
         # print attributes (if any)
         if(print.attributes && !is.null(attributes(x))) {
                 # note: attributes are contained in a named list. Infinite 
recursion
                 # can happen because attributes lists have themselves a 
"names" attribute.
                 if(!is.null(name) && name=="[attributes]") {
#                       print the names attribute of the attribute list
#                       cat(margin,"  ","+ 
","[[attributes]]","<list>\n",sep="")
#                       cat(margin,"  ","  ","- 
","[names]",paste("\'",names(x),"\'",sep="",collapse=","),"\n",sep="")
                         return(invisible(NULL)) # prevent infinite recursion
                 }
                 # print attriutes list
                 print.object(attributes(x),typefun,print.attributes,deparse.level,"[attributes]",level+1)
         }
         invisible(NULL)
}




--------------------------------------------------------------------
Gabriel Baud-Bovy                            tel: (+39) 02 2643 4839
Faculty of Psychology, UHSR University       fax: (+39) 02 2643 4892
via Olgettina, 58, 20132 Milan, Italy


[Rd] Implementation of the names attribute of attribute lists
Gabriel Baud-Bovy