Re: [R-pkg-devel] Conditionally register method with generic in other package
For posterity, the solution I employed did not register the method as a formal S3 method. Functionality in package B was unchanged as long as package B was loaded and attached... which was good enough for my purposes. On Wed, Dec 6, 2017 at 6:45 AM, Joshua Ulrich wrote: > I have a feeling I know the answer to this question, but I'm asking > with the hope that I learn something new. > > Package A defines a S3 generic function, "foo()". Package B defines a > S3 class "bar", and a foo.bar() method. This method is not strictly > necessary for the package to function, and package A has many > dependencies. > > To avoid excessive dependencies, I would like to only register > foo.bar() if package A is installed at the time package B is > installed. If package A is installed after package B, then warn the > user when package B is loaded and/or attached, so they can re-install > A and have foo.bar() registered correctly. > > I could figure out a way to do this manually, but doubt it would be > CRAN-approved. What is the recommended way to handle this situation? > I've received one suggestion to split B into 2 packages: one without > the method, and one with. Are there other alternatives? > > Thanks, > Josh > > -- > Joshua Ulrich | about.me/joshuaulrich > FOSS Trading | www.fosstrading.com > R/Finance 2018 | www.rinfinance.com -- Joshua Ulrich | about.me/joshuaulrich FOSS Trading | www.fosstrading.com R/Finance 2018 | www.rinfinance.com __ R-package-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel
Re: [R-pkg-devel] Conditionally register method with generic in other package
We use this technique in a couple of places: https://github.com/tidyverse/dbplyr/blob/6be777d8b23d588f19c98de52f4e58f16c2ef67e/R/zzz.R Basic idea is to call registerS3method() manually, when needed - it's just a little tricky because the suggested package may be loaded either before or after your package. Hadley On Thu, Dec 7, 2017 at 1:45 AM, Joshua Ulrich wrote: > I have a feeling I know the answer to this question, but I'm asking > with the hope that I learn something new. > > Package A defines a S3 generic function, "foo()". Package B defines a > S3 class "bar", and a foo.bar() method. This method is not strictly > necessary for the package to function, and package A has many > dependencies. > > To avoid excessive dependencies, I would like to only register > foo.bar() if package A is installed at the time package B is > installed. If package A is installed after package B, then warn the > user when package B is loaded and/or attached, so they can re-install > A and have foo.bar() registered correctly. > > I could figure out a way to do this manually, but doubt it would be > CRAN-approved. What is the recommended way to handle this situation? > I've received one suggestion to split B into 2 packages: one without > the method, and one with. Are there other alternatives? > > Thanks, > Josh > > -- > Joshua Ulrich | about.me/joshuaulrich > FOSS Trading | www.fosstrading.com > R/Finance 2018 | www.rinfinance.com > > __ > R-package-devel@r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-package-devel -- http://hadley.nz __ R-package-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel
Re: [R-pkg-devel] Conditionally register method with generic in other package
On Thu, Dec 7, 2017 at 2:44 AM, Bill Denney wrote: > >> On Dec 6, 2017, at 07:45, Joshua Ulrich wrote: >> >> To avoid excessive dependencies, I would like to only register >> foo.bar() if package A is installed at the time package B is >> installed. If package A is installed after package B, then warn the >> user when package B is loaded and/or attached, so they can re-install >> A and have foo.bar() registered correctly. > > One simple solution would be to wrap the instantiation of foo.bar in a > require test: > > if (require(A)) { > foo.bar <- function(...) { > print("To be or not to be") > } > } else { > message("To use the foo.bar function, please install package A.") > } I don't think that will work because the code will be executed at build time, not package-load time. Hadley -- http://hadley.nz __ R-package-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel
Re: [R-pkg-devel] Conditionally register method with generic in other package
Bill, Duncan, Thanks for the replies. On Wed, Dec 6, 2017 at 12:51 PM, Duncan Murdoch wrote: > On 06/12/2017 8:44 AM, Bill Denney wrote: >> >> >>> On Dec 6, 2017, at 07:45, Joshua Ulrich wrote: >>> >>> To avoid excessive dependencies, I would like to only register >>> foo.bar() if package A is installed at the time package B is >>> installed. If package A is installed after package B, then warn the >>> user when package B is loaded and/or attached, so they can re-install >>> A and have foo.bar() registered correctly. >> >> >> One simple solution would be to wrap the instantiation of foo.bar in a >> require test: >> >> if (require(A)) { >>foo.bar <- function(...) { >> print("To be or not to be") >>} >> } else { >>message("To use the foo.bar function, please install package A.") >> } >> > > It's usually better to use requireNamespace("A") instead of require("A") > (and the quotes are needed in requireNamespace(), but optional in > require()). That tries to load the package, but doesn't mess with the search > list. > > But that'll likely cause warnings, unless the same condition is used in the > NAMESPACE file where there should be an entry > > S3method(foo, bar) > > The thing is, I'm not sure if > > if (requireNamespace("A")) > S3method(foo, bar) > > is legal in a NAMESPACE file. > While perhaps not technically illegal, that doesn't work because you need if (requireNamespace("A", quietly = TRUE)) { importFrom(A, foo) S3method(foo, bar) } to prevent an error about being able to find object 'foo' when loading B's namespace. But the importFrom() causes R CMD check to expect a hard dependency on package A (and all its dependencies), which is what I'm trying to avoid... > Duncan Murdoch -- Joshua Ulrich | about.me/joshuaulrich FOSS Trading | www.fosstrading.com R/Finance 2018 | www.rinfinance.com __ R-package-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel
Re: [R-pkg-devel] Conditionally register method with generic in other package
On 06/12/2017 8:44 AM, Bill Denney wrote: On Dec 6, 2017, at 07:45, Joshua Ulrich wrote: To avoid excessive dependencies, I would like to only register foo.bar() if package A is installed at the time package B is installed. If package A is installed after package B, then warn the user when package B is loaded and/or attached, so they can re-install A and have foo.bar() registered correctly. One simple solution would be to wrap the instantiation of foo.bar in a require test: if (require(A)) { foo.bar <- function(...) { print("To be or not to be") } } else { message("To use the foo.bar function, please install package A.") } It's usually better to use requireNamespace("A") instead of require("A") (and the quotes are needed in requireNamespace(), but optional in require()). That tries to load the package, but doesn't mess with the search list. But that'll likely cause warnings, unless the same condition is used in the NAMESPACE file where there should be an entry S3method(foo, bar) The thing is, I'm not sure if if (requireNamespace("A")) S3method(foo, bar) is legal in a NAMESPACE file. Duncan Murdoch __ R-package-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel
Re: [R-pkg-devel] Conditionally register method with generic in other package
> On Dec 6, 2017, at 07:45, Joshua Ulrich wrote: > > To avoid excessive dependencies, I would like to only register > foo.bar() if package A is installed at the time package B is > installed. If package A is installed after package B, then warn the > user when package B is loaded and/or attached, so they can re-install > A and have foo.bar() registered correctly. One simple solution would be to wrap the instantiation of foo.bar in a require test: if (require(A)) { foo.bar <- function(...) { print("To be or not to be") } } else { message("To use the foo.bar function, please install package A.") } Thanks, Bill __ R-package-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel
[R-pkg-devel] Conditionally register method with generic in other package
I have a feeling I know the answer to this question, but I'm asking with the hope that I learn something new. Package A defines a S3 generic function, "foo()". Package B defines a S3 class "bar", and a foo.bar() method. This method is not strictly necessary for the package to function, and package A has many dependencies. To avoid excessive dependencies, I would like to only register foo.bar() if package A is installed at the time package B is installed. If package A is installed after package B, then warn the user when package B is loaded and/or attached, so they can re-install A and have foo.bar() registered correctly. I could figure out a way to do this manually, but doubt it would be CRAN-approved. What is the recommended way to handle this situation? I've received one suggestion to split B into 2 packages: one without the method, and one with. Are there other alternatives? Thanks, Josh -- Joshua Ulrich | about.me/joshuaulrich FOSS Trading | www.fosstrading.com R/Finance 2018 | www.rinfinance.com __ R-package-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel