Just for the record, I did submit PR#15451:

'Bug 15451 - PATCH: namespaceImportFrom() not to warn when the
identical object is imported twice' on 2013-09-10
https://bugs.r-project.org/bugzilla3/show_bug.cgi?id=15451

/Henrik

On Mon, Sep 9, 2013 at 2:37 PM, Henrik Bengtsson <h...@biostat.ucsf.edu> wrote:
> Any intelligent comments on this before I submit a proposal/patch via
> bugs.r-project.org?
>
> /Henrik
>
> On Fri, Aug 30, 2013 at 12:47 PM, Henrik Bengtsson <h...@biostat.ucsf.edu> 
> wrote:
>> On Fri, Aug 30, 2013 at 11:51 AM, Henrik Bengtsson <h...@biostat.ucsf.edu> 
>> wrote:
>>> Hi.
>>>
>>> On Fri, Aug 30, 2013 at 6:58 AM, Paul Gilbert <pgilbert...@gmail.com> wrote:
>>>> This is related to the recent thread on correct NAMESPACE approach when 
>>>> writing S3 methods. If your methods are S4 I think pkgB does not need to 
>>>> export the generic. Just export the method and everything works magically 
>>>> and your problem disappears. For S3 methods there seems to be the 
>>>> difficultly you describe. Of course, the difference between S3 and S4 on 
>>>> this appears somewhat bug like. (I have not tested all this very carefully 
>>>> so I may have something wrong.)
>>>
>>> For the record, you're referring to R-devel thread 'Correct NAMESPACE
>>> approach when writing an S3 method for a generic in another package'
>>> started on Aug 24, 2013
>>> [https://stat.ethz.ch/pipermail/r-devel/2013-August/067221.html].
>>> Yes, it's closely related or possibly the same issue.  However, I do
>>> not find it odd that the S3 generic function needs to be exported
>>> from/available via the namespace.  Hence it needs to be export():ed by
>>> at least one package/namespace.
>>>
>>> The real issue is when two package needs to export a generic function
>>> with the same name, e.g. foo().   If the two generic functions are
>>> defined differently (e.g. different arguments/signatures), they will
>>> be in conflict with each other.  If they are identical, this should
>>> not be a problem, but here I might be wrong.  However, there is also
>>> the special case where one package reexports the generic function from
>>> another package, e.g. PkgB::foo() exports PkgA:foo().  In this case,
>>> the object 'foo' does actually not existing in the name space of
>>> package PkgB - instead it provides a "redirect" to it, e.g.
>>>
>>>> PkgA::foo
>>> function (...)
>>> UseMethod("foo")
>>> <environment: namespace:PkgA>
>>>
>>>> PkgB::foo
>>> function (...)
>>> UseMethod("foo")
>>> <environment: namespace:PkgA>
>>>
>>>> exists("foo", envir=getNamespace("PkgB"), inherits=FALSE)
>>> [1] FALSE
>>>
>>>> exists("foo", envir=getNamespace("PkgB"), inherits=TRUE)
>>> [1] TRUE
>>>
>>>> identical(PkgB::foo, PkgA::foo)
>>> [1] TRUE
>>>
>>>
>>> The warning on "replacing previous import by 'PkgA::foo' when loading
>>> 'PkgC'" that occurs due to import(PkgA, PkgB) is generated in
>>> base::namespaceImportFrom()
>>> [http://svn.r-project.org/R/trunk/src/library/base/R/namespace.R],
>>> simply because it detects that "foo" (=n) has already been imported to
>>> PkgC' namespace (=impenv):
>>>
>>> if (exists(n, envir = impenv, inherits = FALSE)) {
>>>     if (.isMethodsDispatchOn() && methods:::isGeneric(n, ns)) {
>>>         ## warn only if generic overwrites a function which
>>>         ## it was not derived from
>>>         ...
>>>     }
>>>     warning(sprintf(msg, sQuote(paste(nsname, n, sep = "::")),
>>> sQuote(from)), call. = FALSE, domain = NA)
>>> }
>>>
>>> Note how there is already code for avoiding "false" warnings on S4
>>> generic function.  This is what we'd like to have also for S3 generic
>>> functions, but it's much harder to test for such since they're not
>>> formally defined.  However, I'd argue that it is safe to skip the
>>> warning *when the variable to be imported does not actually exist in
>>> the package being imported* (e.g. when just rexported), i.e.
>>>
>>>>svn diff namespace.R
>>> Index: namespace.R
>>> ===================================================================
>>> --- namespace.R (revision 63776)
>>> +++ namespace.R (working copy)
>>> @@ -871,6 +871,10 @@
>>>      }
>>>      for (n in impnames)
>>>         if (exists(n, envir = impenv, inherits = FALSE)) {
>>> +            ## warn only if imported variable actually exists in the
>>> +            ## namespace imported from, which is not the case if
>>> +            ## the variable is rexported from another namespace
>>> +            if (!exists(n, envir = ns, inherits = FALSE)) next
>>>             if (.isMethodsDispatchOn() && methods:::isGeneric(n, ns)) {
>>>                 ## warn only if generic overwrites a function which
>>>                 ## it was not derived from
>>
>> Ok, if import(PkgA, PkgB) and PkgB reexports a *different* foo() than
>> PkgA::foo(), say PkgZ::foo so identical(PkgB::foo, PkgA::foo) is
>> FALSE, then there is indeed a conflict.  An alternative patch:
>>
>>>svn diff namespace.R
>> Index: namespace.R
>> ===================================================================
>> --- namespace.R (revision 63776)
>> +++ namespace.R (working copy)
>> @@ -871,6 +871,11 @@
>>      }
>>      for (n in impnames)
>>         if (exists(n, envir = impenv, inherits = FALSE)) {
>> +            ## warn only if imported variable is non-identical to
>> +            ## the one already imported
>> +            getImp <- get(n, envir = impenv)
>> +            obj <- get(n, envir = ns)
>> +            if (identical(obj, getImp)) next
>>             if (.isMethodsDispatchOn() && methods:::isGeneric(n, ns)) {
>>                 ## warn only if generic overwrites a function which
>>                 ## it was not derived from
>>
>> /Henrik
>>
>>>
>>> I'm planning to propose ("wishlist / enhancement"; it may even be a
>>> bug) this over at https://bugs.r-project.org/.
>>>
>>> Comments, anyone?
>>>
>>> /Henrik
>>>
>>>
>>>> Paul
>>>>
>>>> Henrik Bengtsson <h...@biostat.ucsf.edu> wrote:
>>>>
>>>>>Hi,
>>>>>
>>>>>SETUP:
>>>>>Consider three packages PkgA, PkgB and PkgC.
>>>>>
>>>>>PkgA defines a generic function foo() and exports it;
>>>>>
>>>>>export(foo)
>>>>>
>>>>>PkgB imports PkgA::foo() and re-exports it;
>>>>>
>>>>>importFrom(PkgA, foo)
>>>>>export(foo)
>>>>>
>>>>>PkgC imports everything from PkgA and PkgB:
>>>>>
>>>>>imports(PkgA, PkgB)
>>>>>
>>>>>
>>>>>PROBLEM:
>>>>>Loading or attaching the namespace of PkgC will generate a warning:
>>>>>
>>>>>  replacing previous import by 'PkgA::foo' when loading 'PkgC'
>>>>>
>>>>>This in turn causes 'R CMD check' on PkgC to generate a WARNING (no-go at 
>>>>>CRAN):
>>>>>
>>>>>* checking whether package 'PkgC' can be installed ... WARNING
>>>>>Found the following significant warnings:
>>>>>  Warning: replacing previous import by 'PkgA::foo' when loading
>>>>>'CellularAutomaton'
>>>>>
>>>>>
>>>>>FALSE?
>>>>>Isn't it valid to argue that this is a "false" warning, because
>>>>>identical(PkgB::foo, PkgA::foo) is TRUE and therefore has no effect?
>>>>>
>>>>>
>>>>>/Henrik
>>>>>
>>>>>PS. The above can be avoided by using explicit importFrom() on PkgA
>>>>>and PkgB, but that's really tedious.  In my case this is out of my
>>>>>reach, because I'm the author of PkgA and PkgB but not many of the
>>>>>PkgC packages.
>>>>>
>>>>>______________________________________________
>>>>>R-devel@r-project.org mailing list
>>>>>https://stat.ethz.ch/mailman/listinfo/r-devel

______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

Reply via email to