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

______________________________________________
R-devel@stat.math.ethz.ch mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

Reply via email to