From bodenhofer at bioinf.jku.at  Wed Mar 26 15:11:09 2014
From: bodenhofer at bioinf.jku.at (Ulrich Bodenhofer)
Date: Wed, 26 Mar 2014 15:11:09 +0100
Subject: [Rd] Conflicting definitions for function redefined as S4
	generics
In-Reply-To: <5332DAB1.3090201@gmail.com>
References: <5332B958.5020703@bioinf.jku.at>	<CAOQ5NyfQ8eFc2mLODPR-FB=71UuUjVZjz4srfmRSj-TOJBNmOQ@mail.gmail.com>
	<CADwqtCOPEtXcj_06=PGnrEBMOkyag+KonAM9WKiunL2M8WYp5w@mail.gmail.com>
	<5332DAB1.3090201@gmail.com>
Message-ID: <5332DFFD.6060602@bioinf.jku.at>

First of all, thanks for the very interesting and encouraging replies 
that have been posted so far!

Let me quickly add what I have tried up to now:

- setMethod("sort", signature("ExClust"), function(x, decreasing=FALSE, 
%...%) %...% , sealed=TRUE) without any call to setGeneric(), i.e. 
assuming that setMethod() would implicitly create an S4 generic out of 
the S3 method sort(). Note that '%...%' in the code snippet stands for 
some details that I left out.

- setGeneric("sort", def=function(x, decreasing=FALSE, ...) 
standardGeneric("sort")), i.e. consistency with the S3 generic of sort() 
in 'base', plus the call to setMethod() as shown above.

- setGeneric("sort", signature="x"), i.e. consistency with the generic's 
definition in BiocGenerics, as suggested by Martin Morgan, plus the call 
to setMethod() as shown above.

For all three trials, the result was exactly the same: (1) everything 
works nicely if I load BiocGenerics before apcluster; (2) if I load 
BiocGenerics after apcluster, apcluster's sort() function is broken and 
gives the following error:

Error in rank(x, ties.method = "min", na.last = "keep") :
   unimplemented type 'list' in 'greater'
In addition: Warning message:
In is.na(x) : is.na() applied to non-(list or vector) of type 'S4'

Obviously, sort() is dispatched to the definition made by BiocGenerics:

 > showMethods("sort", includeDefs=TRUE)
Function: sort (package BiocGenerics)
x="ANY"
function (x, decreasing = FALSE, ...)
{
     if (!is.logical(decreasing) || length(decreasing) != 1L)
         stop("'decreasing' must be a length-1 logical vector.\nDid you 
intend to set 'partial'?")
     UseMethod("sort")
}

So the method registered for class 'ExClust' is  lost if BiocGenerics is 
attached. Just for your information: all these tests have been done with 
R 3.0.2 and Bioconductor 2.13 (BiocGenerics version 0.8.0).

Thanks and best regards,
Ulrich



On 03/26/2014 02:48 PM, Duncan Murdoch wrote:
> On 26/03/2014, 9:13 AM, Gabriel Becker wrote:
>> Perhaps a patch to R such that generics don't clobber each-other's 
>> method
>> tables if the signatures agree? I haven't dug deeply, but simply merging
>> the method tables seems like it would be safe when there are no 
>> conflicts.
>>
>> That way this type of multiplicity would not be a problem, though it
>> wouldn't help (as it shouldn't) if the two generics didn't agree on
>> signature or both carried methods for the same class signature.
>
> I don't think R should base the decision on the signature.
>
> There are two very different situations where this might come up. In 
> one, package A and package B might both define a generic named foo() 
> that happens to have the same signature, but with nothing in common. 
> That should be allowed, and should behave the same as when they both 
> create functions with the same name:  it should be up to the user to 
> specify which generic is being called.  If R merged the two generics 
> into one, there would be chaos.
>
> The other situation is more likely to apply to this case.  It sounds 
> as though both apcluster and BiocGenerics are creating a sort() 
> generic by promoting the base package S3 generic into an S4 generic.  
> Clearly they should not be creating separate generics, there's just one.
>
> I don't know if there's something wrong with the way apcluster or 
> BiocGenerics are doing things, or something wrong with the way the 
> methods package is creating the generic, but it sure looks like a bug 
> somewhere.
>
> Duncan Murdoch
>
>>
>> ~G
>>
>>
>> On Wed, Mar 26, 2014 at 4:38 AM, Michael Lawrence 
>> <lawrence.michael at gene.com
>>> wrote:
>>
>>> The BiocGenerics package was designed to solve this issue within
>>> Bioconductor. It wouldn't be the worst thing in the world to depend 
>>> on the
>>> simple BiocGenerics package for now, but ideally the base generics 
>>> would be
>>> defined higher up, perhaps in the methods package itself. Maybe someone
>>> else has a more creative solution, but any sort of conditional/dynamic
>>> approach would probably be too problematic in comparison.
>>>
>>> Michael
>>>
>>>
>>>
>>> On Wed, Mar 26, 2014 at 4:26 AM, Ulrich Bodenhofer <
>>> bodenhofer at bioinf.jku.at
>>>> wrote:
>>>
>>>> [cross-posted to R-devel and bioc-devel]
>>>>
>>>> Hi,
>>>>
>>>> I am trying to implement a 'sort' method in one of the CRAN 
>>>> packages I am
>>>> maintaining ('apcluster'). I started with using setMethod("sort", 
>>>> ...) in
>>>> my package, which worked fine. Since many users of my package are from
>>> the
>>>> bioinformatics field, I want to ensure that my package works smoothly
>>> with
>>>> Bioconductor. The problem is that the BiocGenerics package also 
>>>> redefines
>>>> 'sort' as an S4 generic. If I load BiocGenerics before my package,
>>>> everything is fine. If I load BiocGeneric after I have loaded my 
>>>> package,
>>>> my setMethod("sort", ...) is overridden by BiocGenerics and does 
>>>> not work
>>>> anymore. A simple solution would be to import BiocGenerics in my 
>>>> package,
>>>> but I do not want this, since many of this package's users are outside
>>> the
>>>> bioinformatics domain. Moreover, I am reluctant to include a 
>>>> dependency
>>> to
>>>> a Bioconductor package in a CRAN package. I thought that maybe I could
>>>> protect my setMethod("sort", ...) from being overridden by 
>>>> BiocGeneric by
>>>> sealed=TRUE, but that did not work either. Any ideas are gratefully
>>>> appreciated!
>>>>
>>>> Thanks a lot,
>>>> Ulrich



[Rd] Conflicting definitions for function redefined as S4 generics
Ulrich Bodenhofer