[Rd] Overwriting imported function in another package

Mark.Bravington at csiro.au Mark.Bravington at csiro.au
Tue Aug 9 03:58:27 CEST 2011


[Jeroen Ooms wrote:]
> > I am running into a limitation of the grid::grid.newpage function, for which I would like to overwrite this function
> > with a slightly modified one. Hopefully this is a temporary working solution until the package gets updated. I found a 
> > way to overwrite the function in the package:grid namespace. However, lattice imports grid rather than depending on it. 
> > So I need a way to overwrite this imported version as well. The code below shows the fix which works for ggplot (because 
> > it depends on grid), but it doesn't work for lattice, because it imports grid. Is there any way to overwrite 
> > grid.newpage for all instantiations of it?

[Duncan Murdoch wrote:]
> But everyone who uses your code has a right to expect that other
> packages are not affected by it. 

One should of course only do such things reluctantly and responsibly, as Duncan points out; any changes shouldn't modify *expectable* behaviour of existing functions! But if it's just a bug-fix or innocuous extension of functionality, and/or just in one's own work, then I can see two approaches that might help.

First is to set a load hook something like this (assuming 'newpage' isn't an S3 method, which would entail a tweak):

setHook( packageEvent( 'grid', 'onLoad'), function( ...) { 
  ns <- asNamespace( 'grid')
  unlockBinding( 'grid.newpage', ns)
  assign( 'grid.newpage', << patched version >>, envir=ns)
  lockBinding( 'grid.newpage', ns)
  cat( "Patched grid.newpage\n")
  invisible( NULL)
})

This must be done before the offending package gets loaded, so it won't work eg as an "autopatch" strategy if you want to put it into a package you're writing. But it works fine if you put it in your own .First or other startup mechanism; if you are just helping out some mates, give them this code & tell them how to use it. I've used it for exactly the case mentioned: to "auto-patch" buggy code pending a new release of a buggy package.

Second: *after* loading the offending package, (e.g. in the '.onLoad' of your own package, if you're putting this into a package) you could use 'fun.locator' in 'mvbutils' to find all instances of the offending function including imports, and then change each copy manually. An example is 'mtrace' in 'debug', which deliberately tries to find and change all copies of a function. (Whether 'fun.locator' finds absolutely every copy, I'm not sure, but it does try; NB it won't work as-is for S4, and needs to be used differently for ref classes.) This is uglier, but should be automatic (and should also ensure that any subsequent imports of the offender pick up the patched version, though I haven't checked).

Note that this won't work retrospectively for copies that are imported into a package namespace under an alias, which I think used to be a theoretical possibility but may not be any more.

HTH
Mark

-- 
Mark Bravington
CSIRO Mathematical & Information Sciences
Marine Laboratory
Castray Esplanade
Hobart 7001
TAS

ph (+61) 3 6232 5118
fax (+61) 3 6232 5012
mob (+61) 438 315 623

-- 
Mark Bravington
CSIRO Mathematical & Information Sciences
Marine Laboratory
Castray Esplanade
Hobart 7001
TAS

ph (+61) 3 6232 5118
fax (+61) 3 6232 5012
mob (+61) 438 315 623

Duncan Murdoch wrote:
> On 08/08/2011 8:40 AM, Jeroen Ooms wrote:
>>>  Yes, modify the source and recompile R.
>> 
>> That is what I am doing now, but can't expect that everyone who uses
>> my code is willing to recompile R from src...
> 
> But everyone who uses your code has a right to expect that other
> packages are not affected by it. 
> 
> Duncan Murdoch
> 
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel


More information about the R-devel mailing list