On 11-02-28 11:17 PM, Jeroen Ooms wrote:> I am trying to encode arbitrary S3 objects by recursively looping over the
> object and all its attributes. However, there is an unfortunate feature of
> the attributes() function that is causing trouble. From the manual for
> ?attributes:
>
> The names of a pairlist are not stored as attributes, but are reported as
if
> they were (and can be set by the replacement method for attributes).
>
> Now because of this, my program ends up in infinite recursion, because it
> will try to encode
> attributes(attributes(attributes(attributes(list(foo=123)))) etc. I
can't
> remove the 'names' attribute, because this will actually affect the
list
> structure. And even when I do:
>
> attributes(attributes(obj)[names(attributes(obj)) != "names"])
>
> This will keep giving me a named list. Is there any way I can get the
> attributes() of a list without it reporting the names of a list as
> attributes? I.e it should hold that:
>
> atr1<- attributes(list(foo="bar"));
> atr2<- attributes(list());
> identical(atr1,atr2);
The names of a list (a generic vector) are attributes, just like the
names of other vectors. The documentation is talking about pairlists, a
mostly internal structure, used for example to store parts of
expressions. So your premise might be wrong about the cause of the
recursion...
But assuming you really want to see all attributes except names. Then
just write your own version:
nonameattributes <- function(obj) {
result <- attributes(obj)
if (!is.null(result$names))
result$names <- NULL
# This removes the empty names of the result if there were no other
# attributes. It's optional, but you said you wanted
# identical(atr1, atr2)
if (!length(result))
names(result) <- NULL
result
}
You can make the conditional more complicated, only making the change
for pairlists, etc., using tests on typeof(obj) or other tests.
Duncan Murdoch