Gabriel Baud-Bovy
2005-May-10 14:08 UTC
[Rd] Implementation of the names attribute of attribute lists
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
Reasonably Related Threads
- Fwd: Re: Implementation of the names attribute of attribute lists
- obscure error with subsetting as.list() of a function then (PR#9504)
- obscure error with subsetting as.list() of a function then (PR#9506)
- promptFunctions() to handle multiple names
- Help interpreting output of Rprof