1

When using S3 methods from dependent packages, how do I ensure that a package loads (and attaches?) all dependent packages when called using the double colon (::) operator without a prior library() call?

I am developing a package package3 that uses package1 and package2. package1 defines an S3 method funky and package2 defines methods for additional types. If I use the funky method in my own package, package3, then R cannot find the relevant S3 method, even though package3 imports both package1 and package2.

The actual problems occurs with the officer and mschart project, but it is generic and I have created a reusable example using 3 separate packages in RStudio

Context

package1 Defines funky(arg) and funky.character(arg). Both methods are exported

package2 Defines funky.numeric(arg). Imports package1 However, Roxygen does not generate a S3method in NAMESPACE

package3 Defines hello() which calls funky(100) (i.e the numeric method should be called). Imports package1 and package2 (I've also tried with depends),

Reproduce the problem

package3::hello() generates an error regarding the missing S3 method

Workaround

library(package3)
package3::hello()

However, because the package will be used internally within our company I can't expect everyone to know that library() has to be called first

Any ideas on how I can ensure that all relevant S3 methods are available even when using the double colon (::) operator?

Many thanks in advance

Jonas

Jonas
  • 95
  • 2
  • 2
  • 9

1 Answers1

1

You could add the line

Depends: package2

To the DESCRIPTION file in your package's root directory. This ensures that anyone who installs your package will automatically install package2. It also makes sure that package2 is loaded and on the users' search path any time your package is loaded.

Another possibility would be to add

#' @export
funky.numeric <- package2:::funky.numeric

Near the top of your main R file. This should work in practice if this is a package just for use within your own company, though it wouldn't be allowed on CRAN. This should allow users to do package1::funky(x) with appropriate dispatch.

Allan Cameron
  • 147,086
  • 7
  • 49
  • 87
  • 1
    Hi Allan, Thank you for your answer. Unfortunately the Depends does not address the issue as the package is still not attached when invoking the function using the double colon (::) operator Regarding the workaround indeed I can call the specific function but then some of the purpose of the S3 function is lost. In the minimal example I could call it but in practice I do not know the exact type when calling the S3 method. – Jonas Sep 21 '20 at 07:56
  • @Jonas but why not have all the relevant S3 methods exported from your package like above? It's only a single line per class. Remember, you are asking "how do I get my package to select an unexported method from a different package without loading or attaching that different package?". The answer surely has to involve copying the method from the other package or forcing it to be loaded. You have to access the code _somehow_. – Allan Cameron Sep 21 '20 at 08:06