From jmc at r-project.org  Sat Jul 28 15:38:45 2007
From: jmc at r-project.org (John Chambers)
Date: Sat, 28 Jul 2007 09:38:45 -0400
Subject: [Rd] R2.6 bug in arithmetics of S4 classes inherited from
 'array', or intended behavior?
In-Reply-To: <1185187439.6294.58.camel@dirac>
References: <1185181337.6294.29.camel@dirac> <1185187439.6294.58.camel@dirac>
Message-ID: <46AB46E5.2080301@r-project.org>

Yes, this is the intended behavior.  Nothing to do with implicit 
generics, but with some ongoing changes to make class "structure" and 
related classes such as "array" give trustworthy results consistent with 
the S language idea of vector structures.  There's a short note in NEWS 
about the changes, added for the revision where the change was introduced.

As for programming your class, using showMethods("+") as below will tell 
you that the method is inherited from the group generic function "Ops", 
so a method for that function is needed, if you _really_ know what the 
results should be.

The behavior of the base package code for operations is unacceptable for 
trustworthy computations with classes.  Roughly, it takes the attributes 
of the left-hand operand and inserts those into the result of operating 
on the vector or array part.  So in the example below we have two  
unrelated classes that both extend "array".  A mixed operation gives a 
result from class "A1" if done in one order and from "A2" if done in the 
other order.  Both are likely wrong and quite possibly seriously misleading.

Even if the two objects came from the same class, copying one set of 
attributes makes sense only if the two sets are identical (an expensive 
test) and not necessarily even then, if any of the attributes would be 
invalidated by the operation.

Two acceptable results are either to reduce to the common inheritance 
(array, here) or to call the result undefined and throw an error.  The 
current implementation in 2.6.0  is the first, as the example shows:

 > setClass("A1", contains="array", representation(flag = "character"))
[1] "A1"
 > setClass("A2", contains="array", representation(positive = "logical"))
[1] "A2"
 > a1 = new("A1", array(1:8, rep(2,3)), flag = "test")
 > a2 = new("A2", array(8:1, rep(2,3)), positive = rep(TRUE,8))
 > a1+a2
, , 1

     [,1] [,2]
[1,]    9    9
[2,]    9    9

, , 2

     [,1] [,2]
[1,]    9    9
[2,]    9    9

 > showMethods("+")
Function: + (package base)
e1="A1", e2="A2"
    (inherited from: e1="array", e2="array")
    (definition from function "Ops")


Oleg Sklyar wrote:
> Narrowed down to Rev. 42246:
>
> * ~/R/Rsvn: svn up -r42245
> * ~/R/Rsvn: make
> * ~/R/Rsvn: Rsvn CMD INSTALL ~/tmp/EBImage_2.1.13.tar.gz
> * ~/R/Rsvn: Rsvn
>   
>> version$version.string
>>     
> [1] "R version 2.6.0 Under development (unstable) (2007-07-16 r42245)"
>   
>> library(EBImage)
>> a <- Image(0,c(2,2))
>> class(a+a)
>>     
> [1] "Image"
> attr(,"package")
> [1] "EBImage"
>
> * ~/R/Rsvn: svn up -r42246
> * ~/R/Rsvn: make
> * ~/R/Rsvn: Rsvn CMD INSTALL ~/tmp/EBImage_2.1.13.tar.gz
> * ~/R/Rsvn: Rsvn
>   
>> version$version.string
>>     
> [1] "R version 2.6.0 Under development (unstable) (2007-07-16 r42246)"
>   
>> library(EBImage)
>> a <- Image(0,c(2,2))
>> class(a+a)
>>     
> [1] "array"
>
> * ~/R/Rsvn: svn log -r42246
> ------------------------------------------------------------------------
> r42246 | jmc | 2007-07-16 14:32:16 +0100 (Mon, 16 Jul 2007) | 1 line
>
> implicitGeneric() and structure class
> ------------------------------------------------------------------------
>
>   


[Rd] R2.6 bug in arithmetics of S4 classes inherited from 'array', or intended behavior?
John Chambers