From ripley at stats.ox.ac.uk  Sat Dec 13 08:36:27 2003
From: ripley at stats.ox.ac.uk (Prof Brian Ripley)
Date: Sat Dec 13 08:35:24 2003
Subject: [Rd] Reorganization of packages in the R distribution
In-Reply-To: <Pine.LNX.4.44.0312121933280.15316-100000@itasca2.stat.uiowa.edu>
Message-ID: <Pine.LNX.4.44.0312130653540.17011-100000@gannet.stats>

Thanks Luke for longer explanation.  I had been writing one between
meetings yesterday (in response to the original complaint), which almost
duplicated this.  Three points from mine not yet covered explicitly and
which provide further pieces of rope:

1) Objects from tframe may or may not have a class. If they do, you could 
implement start.tframe to handle them partly and otherwise call 
NextMethod().  If they do not, you could add a class (preferably) or you 
could take over start.default.  It is much safer to take over a method 
than mess with a generic.

2) Redefining the generic start() probably does not do what you think it
does since the advent of namespaces.  Now all the ts functions are in a
namespace (true since 1.7.0), all of them will use the system's start()
and not yours.  One loophole (deliberate) is that the system start()
generic does not look within the current namespace first for methods (as
normally functions are looked up), so if you redefine a method, you will
get your copy used by the system generic.  (Conversely, if you redefine a 
generic it only gets used in your code and it may well not see the 
system's methods.)

3) I am reluctant to even mention this, but you could add a namespace to 
your package, have a generic within it and register the system's methods 
as methods for your generic.  Don't go there.  And don't even think about 
redefining the system's generic in its namespace, even though there is a 
documented way to do so.

On Fri, 12 Dec 2003, Luke Tierney wrote:

> On Fri, 12 Dec 2003, Paul Gilbert wrote:
> 
> > If  I understand this change correctly, I think is wrong for R-core to 
> > think it is a small change. It has much more serious consequences for me 
> > than any changes introduced  R 1.0. It definitely should not be 
> > introduced at a dot level release unless there is a fairly simple 
> > mechanism to deal with the implications. It breaks  6 of my 9 packages 
> > on CRAN at a fairly fundamental level,  2 more at a less serious level,  
> > and some packages I have not yet release.

But there is a lack of independence: it breaks no other package on CRAN 
(all the other breakages are looking explicitly in what are now wrong 
places, in some cases calling C-level entry points which are not in the 
API).

> > Perhaps my programming technique is not correct. I always considered 
> > this trick to be a work-around for a short coming in R/S.   The issue is 
> > that the correct way to do this needs to be implemented before the trick 
> > that allows a work-around is eliminated.
> > 
> > Paul Gilbert
> > 
> > Prof Brian Ripley wrote:
> > 
> > >On Fri, 12 Dec 2003, Paul Gilbert wrote:
> > >
> > >  
> > >
> > >>Prof Brian Ripley wrote:
> > >>
> > >>    
> > >>
> > >>>There are a small number of CRAN packages that attempt to modify system
> > >>>functions and so will need updating.  (Known examples are in dse:tframe,
> > >>>gregmisc and mclust and some testing code elsewhere.)
> > >>>
> > >>>      
> > >>>
> > >>Brian
> > >>
> > >>What do you mean by "updating?"  In tframe I modify a few functions like
> > >>
> > >>     start <- function (x, ...) if (is.Ttframed(x)) start(tframe(x), 
> > >>...) else UseMethod("start")
> > >>
> > >>If that can no longer be done then this is a serious fundamental change 
> > >>that breaks all my code. I hope that is not what you mean. I'm just 
> > >>going away for a week, but will follow up when I return.
> > >>    
> > >>
> > >
> > >It's always been incorrect code, and it no longer works.  You should not
> > >be masking system generics, as the namespace registration mechanism does
> > >not work on your version.
> > >
> > >  
> > >
> 
> There are a number of options, depending on what you are trying to do.
> If you want to make a definition of how the function `start' should
> handle a TtFramed object in a way that should be visible to functions
> defined in other packages that use the function start from the R core
> packages (formarly base, not stats), then you can do that one of two
> ways. The first is the disciplined and supported way: use the fact
> that `start` is a generic and define a method for it, as was already
> suggested.  That is the point of defining `start' as a generics.  The
> undisciplined way it to change the definition in the stats package.
> This can be done.  It is hard to do, and that is deliberate.
> 
> If your intent is to define a function of your own for use in your
> packages that does something you want in one particular case but
> otherwise defers to the function `start' in base then you can do that
> too.  If this is what you want then things would be clearer if you
> used a different name, like
> 
> pgStart <- function (x, ...) {
>     if (is.Ttframed(x)) start(tframe(x), ...)
>     else start(x, ...)
> }
> 
> If for some reason you must use the smae name, even though that may
> not be doing what you think it is doing, then you can explicitly defer
> to the version in stats with
> 
> start <- function (x, ...) {
>     if (is.Ttframed(x)) stats::start(tframe(x), ...)
>     else stats::start(x, ...)
> }
> 
> So we have infact implemented several nice pieces of rope for your use ...
> 
> Best,
> 
> luke
> 
> 
> 

-- 
Brian D. Ripley,                  ripley@stats.ox.ac.uk
Professor of Applied Statistics,  http://www.stats.ox.ac.uk/~ripley/
University of Oxford,             Tel:  +44 1865 272861 (self)
1 South Parks Road,                     +44 1865 272866 (PA)
Oxford OX1 3TG, UK                Fax:  +44 1865 272595


[Rd] Reorganization of packages in the R distribution
Prof Brian Ripley