Skip to content

[Bioc-devel] Nasty function collision

12 messages · James W. MacDonald, Seth Falcon, Robert Gentleman +3 more

#
I am having a nasty function collision in my affycoretools package that
is causing things to error out. I have tracked the problem down to the
getURL() functions that are defined in RCurl and annaffy. If I load
RCurl first and then annaffy, getURL() is silently masked, probably
because it is an S4 function in annaffy and a regular function in RCurl.


If I do the opposite, R is nice enough to mention that I have just
masked a function from annaffy. 

In the past I got around this problem by importing annaffy rather than
listing it in the Depends line in the DESCRIPTION file, and load()ing it
when needed. This worked out OK because one is likely to be using either
annaffy to create output, or biomaRt, but not usually both, so the
masking problem was a moot point. Having annaffy in Imports ensured that
things like biocLite() would automatically install it as a dependency.

Unfortunately now R CMD check complains about "'library' or 'require'
calls not declared from: annaffy" and points me to Creating R Packages
and the DESCRIPTION file entry, which doesn't really enlighten.

Any suggestions?

Best,

Jim





James W. MacDonald, M.S.
Biostatistician
Affymetrix and cDNA Microarray Core
University of Michigan Cancer Center
1500 E. Medical Center Drive
7410 CCGC
Ann Arbor MI 48109
734-647-5623


**********************************************************
Electronic Mail is not secure, may not be read every day, and should not be used for urgent or sensitive issues.
#
"James MacDonald" <jmacdon at med.umich.edu> writes:
Since annaffy has a NAMESPACE, this is easy to resolve.  You can:

i) Make calls to annaffy::getURL where appropriate

ii) "Rename" annaffy's getURL function in your package code:

        annaffy_getURL <- annaffy::getURL

iii) Rename annaffy's getURL at import time:

       importFrom("annaffy", foo=getURL)

IMO, this sort of conflict is really not nasty at all.  What would be
nasty is to expect package developers to keep in mind the global name
space consisting of the union of all existing packages and to name
their functions accordingly.
Seems odd that you only sometimes get a warning since both packages
have a name space.  But perhaps it depends on details of
import/require/depend, etc.
Listing it in Imports in DESCRIPTION implies you really import it in
the NAMESPACE file -- and that means it gets loaded (but not attached
to the search path).
Separate issue which might have a reasonable workaround, but I think
you want i, ii, or iii above. :-)

Best,

+ seth
#
That is IMHO pretty much it - not a problem, and why namespaces exist.
I really think that you want to use iii) in preference to either i) or 
ii), and if you only want that getURL then I would import it with that name.
Seth Falcon wrote:

  
    
#
I would think that this is effectively the case.
'getURL' is declared as a generic (which is apparently
not considered overriding anything in the search path).

This should not be so much of a problem, as setGeneric is
described to behave by default:
"Typically, an existing non-generic function becomes the default method,
but there is much optional control."

However, some code in annaffy could be the causing trouble
(by enforcing a change of the default behavior mentioned above).

The file annotation.R in annaffy (in devel) has:

setMethod("getURL", "ANY", function(object) {

    return(character(0))
})


Waiting for a possible fix in annaffy (I might have overlooked
aspects of the problem, and there might be a reason for
enforcing a default behavior returning 'character(0)'), you
might have some luck in calling directly getURL in its namespace
(i.e., RCurl::getURL)

HTH,

L.
#
Thanks for the input. However, I am not sure if any of these suggestions 
are applicable. I don't ever call getURL() directly; it gets called as a 
result of calling saveHTML() in annaffy, which outputs an HTML table, or 
it gets called by useMart() in biomaRt when trying to connect to a 
Biomart using the RCurl package.

It seems to me that Laurent has the best suggestion - getURL() in 
annaffy has a method:

setMethod("getURL", "ANY", function(object) {

     return(character(0))
})


Which to an S4 maven may be useful, but pretty much torches the getURL() 
in RCurl. It seems to me that this method isn't particularly useful (is 
it?), so maybe the best course of action is to convince Colin Smith to 
remove this particular method.

The other possibility is to get Steffen Durinck to change biomaRt to use 
RCurl::getURL().

Or am I still missing something?

Best,

Jim
Robert Gentleman wrote:

  
    
#
This is sort of passing the buck but it seems like it is the  
responsibility of client code to resolve collisions like this when  
both colliding packages already use namespaces. I think the best  
option would be to have biomaRt use RCurl::getURL() instead of getURL 
(). Short of that, you might be able to write a function in  
affycoretools which redefines the behavior of getURL with an "ANY"  
argument in the global namespace:

setMethod("getURL", "ANY", function(object) {

     RCurl::getURL(object)
})

Because annaffy is in its own namespace, it shouldn't be affected by  
that change. (?) I'm not sure if this suggestion would actually work  
and it could be regarded as messy hackery.

Just my two cents.

-Colin
On Oct 31, 2006, at 11:08 , James W. MacDonald wrote:

            
#
I agree with Colin and will modify the biomaRt code so it uses 
RCurl::getURL().
Thanks Jim, for pointing out this problem.

Cheers,
Steffen
Colin A. Smith wrote:
#
"James W. MacDonald" <jmacdon at med.umich.edu> writes:
Then the problem is in these packages and they need to take advantage
of the name space utilities. 

Ah, annaffy has this:

if( !isGeneric("getURL") )
    setGeneric("getURL", function(object) standardGeneric("getURL"))

This is familiar legacy code that worked around issues in the S4
system.  It is no longer needed, and in this case, I'm pretty sure it
is causing trouble.  Removing the check and just defining the generic
in the annaffy package should help.

For biomaRt, it might make sense to import RCurl or at least getURL in
the NAMESPACE file.

Jim, can you try patching annaffy as suggested and see if this
resolves the issue?

+ seth
#
Thanks Steffen. FWIW, Colin's suggestion appears to work as well (and I 
am certainly not averse to messy hackery - I may well make a living at 
it ;-D).

Best,

Jim
Steffen Durinck wrote:

  
    
#
"Colin A. Smith" <colin at colinsmith.org> writes:
Yes, but your code, Colin, is attaching a rather broad method on
someone else's generic (can't say who's actually).  Since getURL in
RCurl is _not_ generic, it really slams getURL.

Code that does the optional generic definition really needs to go away
at this point (I know it was needed at some point, so I'm not trying
to point a finger or anything).  To be specific, I'm referring to any
code that does something along the lines of:

    if (!isGeneric("foo"))
       setGeneric("foo") ...


Yes, biomaRt and other RCurl user's should import getURL from RCurl (I
think that is enough, I don't think you need RCurl::getURL), but you
may be right that there is a larger issue when a generic gets
defined... will explore that one.

Best,

+ seth
#
please consider the option of importing getURL, that is the better way 
to do it, then you get the one you want for all functions, and it is 
obvious. using RCurl::getURL, should not be the preferred option
Steffen Durinck wrote:

  
    
#
Seth Falcon wrote:

            
I tried removing the if(!isGeneric("foo")) lines from annaffy and 
re-installed, and it didn't make a difference. However, re-setting the 
method as Colin suggested:

setMethod("getURL", "ANY", function(object) {
     RCurl::getURL(object)
})

did work, do it appears to me that the real cause of the collision is 
this particular method rather than co-opting an existing generic.

Best,

Jim