Skip to content

function remains loaded in the search space after detaching the package

10 messages · Martin Maechler, Brian Ripley, Joris Meys +1 more

#
I ran into some very irritating behaviour I don't understand.  Let me
illustrate with the package gdata() and the function
print.object_size() :
6.3 Kb
A single object matching ?print.object_size? was found
It was found in the following places
  registered S3 method for print from namespace utils
  namespace:utils
with value
...

All is well. So now I load gdata
Loading required package: gdata
...
The following object(s) are masked from ?package:utils?:

    object.size

OK, this is what I would expect:
[1] 6424
2 differing objects matching ?print.object_size? were found
in the following places
  registered S3 method for print from namespace utils
  namespace:gdata
  namespace:utils
Use [] to view one of them

Now I detach gdata again
But the function print.object_size is still the default for object_size objects!
[1] 6424

And it can still be found as well:
2 differing objects matching ?print.object_size? were found
in the following places
  registered S3 method for print from namespace utils
  namespace:gdata
  namespace:utils
Use [] to view one of them

Am I missing something?

Cheers
Joris
#
> I ran into some very irritating behaviour I don't
    > understand.  Let me illustrate with the package gdata()
    > and the function print.object_size() :

    >> print(object.size(iris),units='Kb')
    > 6.3 Kb
    >> getAnywhere(print.object_size)
    > A single object matching ?print.object_size? was found It
    > was found in the following places registered S3 method for
    > print from namespace utils namespace:utils with value ...

    > All is well. So now I load gdata

    >> require(gdata)
    > Loading required package: gdata ...  The following
    > object(s) are masked from ?package:utils?:

    >     object.size

    > OK, this is what I would expect:

    >> print(object.size(iris),units='Kb')
    > [1] 6424
    >> getAnywhere(print.object_size)
    > 2 differing objects matching ?print.object_size? were
    > found in the following places registered S3 method for
    > print from namespace utils namespace:gdata namespace:utils
    > Use [] to view one of them

    > Now I detach gdata again

    >> detach(package:gdata)

    > But the function print.object_size is still the default
    > for object_size objects!

    >> print(object.size(iris),units='Kb')
    > [1] 6424

    > And it can still be found as well:

    >> getAnywhere(print.object_size)
    > 2 differing objects matching ?print.object_size? were
    > found in the following places registered S3 method for
    > print from namespace utils namespace:gdata namespace:utils
    > Use [] to view one of them

    > Am I missing something?

Yes:  the argument  'unload'   of detach().

In general: Now that every package has a namespace,
you (and others) should learn the difference between 
attaching and loading - and hence  detach()ing and unloading
a package with its namespace.

 ?detach
 ?library

etc should give a good start.

Martin Maechler, ETH Zurich
#
Aaargh... I should RTFM more closely.  Thanks for pointing this out.

On Fri, Feb 24, 2012 at 12:20 PM, Martin Maechler
<maechler at stat.math.ethz.ch> wrote:

  
    
#
On 24/02/2012 11:20, Martin Maechler wrote:
A very good point, but actually there is more to this one.  'gdata' 
registers an S3 method which overwrites the one from utils.  Unloading a 
namespace does not unregister its methods (and registration has no 
stack, so there is no way R knows what was there before).
#
Indeed, when trying :
[1] 6424

However, when I do :
used (Mb) gc trigger (Mb) max used (Mb)
Ncells 380471 10.2     667722 17.9   597831 16.0
Vcells 353363  2.7     905753  7.0   902804  6.9

The function used is still print.object_size from gdata
[1] 6424

But it can't be found any more...
A single object matching ?print.object_size? was found
It was found in the following places
  registered S3 method for print from namespace utils
  namespace:utils
with value
... (here is indeed the code of the original print.object_size)

This is not some kind of behaviour one would expect. I have no clue
how to solve this, but I believe it's safe to say that there's room
for improvement somewhere to avoid calling a function that's
apparently not in the search space. Any other ideas?

Cheers
Joris

On Fri, Feb 24, 2012 at 1:08 PM, Prof Brian Ripley
<ripley at stats.ox.ac.uk> wrote:

  
    
#
On Fri, 24 Feb 2012, Joris Meys wrote:

            
As

getS3method('print', 'object_size')

would have confirmed the expectations of a 'one' with a less sketchy
understanding of R.
R relies very heavily on 'calling a function that's apparently not in 
the search space': that's much of the point of namespaces.

Professor Ripley

  
    
#
2012/2/24 Prof Brian Ripley <ripley at stats.ox.ac.uk>:
Yes, getS3method() sends you -not very surprisingly- to the one from
gdata. I realized, as print(object.size(iris)) gets that one as well,
and even in my sketchy understanding of R I suspect that both actions
have a similar underlying mechanism. But that's not my point.

Why would I have to expect the gdata version is still used (under the
correct assumption that I haven't been writing on the R source code
myself)? As a maybe-not-so-smart basic user of R, I would expect that
detach() and eventually unloadNamespace() would revert the effect of
library() (and loadNamespace() ). Apparently they don't.

The only way to reverse the action of require(gdata) seems to be to
restart R. That's at least what my limited brain could understand from
the valuable information given by both you and Martin. Seemingly
having to restart an application to undo an action, even in the
presence of functions with names that make you believe they revert a
former action, might in general be conceived as rather unexpected by
somebody with the same sketchy understanding of R as me. I would be
delighted if you could explain to me which part of R I understand
wrongly to come to this silly observation.

Sincerely,
Joris
#
fortunes::fortune('WTFM') applies.  As already pointed out, ?detach 
says

      If a package has a namespace, detaching it does not by default
      unload the namespace (and may not even with ?unload=TRUE?), and
      detaching will not in general unload any dynamically loaded
      compiled code (DLLs).  Further, registered S3 methods from the
      namespace will not be removed.  If you use ?library? on a package
      whose namespace is loaded, it attaches the exports of the already
      loaded namespace.  So detaching and re-attaching a package may not
      refresh some or all components of the package, and is inadvisable.

And that is explicitly mentioned on ?unloadNamespace ....
On Fri, 24 Feb 2012, Joris Meys wrote:

            

  
    
#
Maybe I should rephrase:

As mentioned by Martin, by you and by TFM (which I read),
unloadNamespaces does not remove registered S3 methods. I got the
message before. As to why it has to be this way, the people that WTFM
didn't really add much information to TFM for those who RTFM (nor do
they have to). I merely wondered why it had to be that way out of
interest, but maybe formulated my question in a less clear and more
offensive way.

So:

Given the fact that S3 methods are not removed by unloading a namespace:

 - What is the reason for this, as I would naively assume removing
them when unloading a namespace seems more useful?
 - How do you remove them without having to restart R?

Sincerely,
Joris

2012/2/24 Prof Brian Ripley <ripley at stats.ox.ac.uk>:

  
    
#
On 24.02.2012 16:55, Joris Meys wrote:
Because there are no mechanisms implemented that keep the old 
information, i.e. before things got registered.
That is not possible.

Uwe Ligges