Thank you, this is very helpful. I am a little confused now about the
structure of a list though. If the names of the list-elements is truly an
attribute that is stored in another list this would lead to an infintely
recursing object?

How could I iterate over the full object tree, without getting into infinite
recursion if every list's attributes is another list with at least a 'names'
attribute?





On Tue, Mar 1, 2011 at 2:30 AM, Duncan Murdoch <murdoch.duncan@gmail.com>wrote:

> 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
>
>
>

	[[alternative HTML version deleted]]

