[R] Defining class as a member of another class

Wacek Kusnierczyk Waclaw.Marcin.Kusnierczyk at idi.ntnu.no
Sun Jun 28 12:14:31 CEST 2009


Peter Dalgaard wrote:
> Wacek Kusnierczyk wrote:
>> Martin Morgan wrote:
>>> Gabor Grothendieck wrote:
>>>  
>>>> Try this:
>>>>
>>>>   
>>>>> setClass("zoo")
>>>>>       
>>>> [1] "zoo"
>>>>     
>>>
>>> 'zoo' is I guess intended as an S3 class (from library zoo), so
>>> setOldClass('zoo') is appropriate. Otherwise, setClass("zoo") creates a
>>> new virtual class.
>>>
>>>  
>>>>> setClass("Work",representation=(x="zoo"))
>>>>>       
>>>
>>> This syntax representation=(x="zoo") is doing something quite strange;
>>>   
>>
>> Strange?  If there's is something strange here, it's is the idea that
>>
>>    setClass('bar', representation=c('foo'))
>>
>> creates a subclass of 'foo', while
>>
>>    setClass('bar', representation=c(x='foo'))
>>
>> creates a class with 'foo' as a component.  it's just a design 
>> choice, but it's confusing and surely begging for trouble.  but given 
>> this is as it is, there is nothing strange with
>>
>>    setClass('bar', representation=(x='foo'))
>>
>> as far as i am able to understand r, it's equivalent to
>>
>>    x = 'foo'
>>    setClass('bar', representation='foo')
>>
>> hence, bar extends foo.  just a little and useless pattern.
>
> Yes, assuming standard evaluation. 

depending on what you mean by 'standard evaluation'.  r has more than 
one evaluation standard, depending on what sort of function is called.  
setClass is a regular function, and as such it should conform to the 
evaluation rule whereby the arguments are passed as promises.  even with 
this 'standard evaluation', which allows for the argument to be 
deparsed, the pattern does not seem to be particularly useful (though 
yes, you spare typing 'c').


> I think the point was that if you were expecting it to generate a slot 
> "x", then setClass() would need to do something strange internally -- 
> recognizing the assignment and deparsing its LHS for the component name.
>

well, it would not be that strange, given that a substantial bunch of r 
functions do such ugly trickery to their arguments -- they deparse them 
and use (parts of) the argument expressions rather than their values.  
it's certainly not implausible that the convoluted s4 system would do 
such stuff, too.

> Having results depending on whether or not a character vector is named 
> does look like an accident waiting to happen, I agree. However, as of 
> 2.9.0, Martin's code doesn't seem to actually work:
>
> > setClass("Work",representation=c(x="integer"))
> Error in validObject(.Object) :
>   invalid class "classRepresentation" object: invalid object for slot 
> "slots" in class "classRepresentation": got class "character", should 
> be or extend class "list"


indeed.

>
> The documentation says that representation is a named _list_, so you'd 
> want representation=list(x="integer") to get slot "x".

i haven't read the whole ?setClass, but at least the arguments section 
does not explain that you can actually pass a single string, not a list, 
to denote inheritance.  if this is a deprecated pattern, why not 
deprecate it explicitly, in the docs and with a runtime warning.  if it 
is not, why not document it? 

the following is confusing:

    setClass('foo')
    setClass('bar')

    setClass('dee', representation=c('foo', 'bar'))
    # error: invalid object for slot 'slots', got class 'character', 
should be or extend class 'list'

while

    setClass('dee', representation=c('foo'))

works.  the error message is rather uninformative.  ?setClass says:

"          Backward compatibility and compatibility with S-Plus allows
          unnamed elements for superclasses
"

and i would think that if c('foo') is allowed, c('foo', 'bar') should 
work too, just specifying two superclasses rather than one.

vQ




More information about the R-help mailing list