Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle dynamic R6 methods #1246

Open
yogat3ch opened this issue Sep 3, 2021 · 3 comments
Open

Handle dynamic R6 methods #1246

yogat3ch opened this issue Sep 3, 2021 · 3 comments
Labels
feature a feature request or enhancement R6 6️⃣ reprex needs a minimal reproducible example

Comments

@yogat3ch
Copy link

yogat3ch commented Sep 3, 2021

Hi roxygen2 crew,
This is a feature request regarding integrating roxygen2 support for more flexible R6 method definitions that allow for functions to be defined elsewhere or to be defined with rlang::new_function.
Right now extract_r6_methods relies on utils::getSrcLocation which requires that the method be declared in full inside the R6 class. In most instances this works fine.
However, there are instances where this breaks down.
An R6 method could be a function with many arguments or a lengthy default input for an argument that would otherwise create an extraordinarily verbose class definition that becomes difficult to navigate in the source editor.
Two methods exists for solving this:

  • Define the function in another file and just pass it as a named method
  • Use rlang::new_function that allows for a long pairlist to be defined elsewhere and expanded with !!!
    utils::getSrcLocation inside extract_r6_methods will return NULL if a method is defined in either of these ways, causing the map_int in which it's embedded to give an obtuse error of this nature:
Error: Result 3 must be a single integer, not NULL of length 0

Is it possible to locate the method using the appearance of it's name in the class definition instead?

@gaborcsardi gaborcsardi added feature a feature request or enhancement R6 6️⃣ labels Sep 5, 2021
@hadley hadley changed the title More robust alternative to utils::getSrcLocation in extract_r6_methods that supports functions defined elsewhere and/or rlang::new_function Handle dynamic R6 methods Mar 29, 2022
@hadley hadley added the reprex needs a minimal reproducible example label Mar 29, 2022
@hadley
Copy link
Member

hadley commented Mar 29, 2022

@yogat3ch can you please start by providing a simple example of an R6 class that illustrates this problem?

@yogat3ch
Copy link
Author

yogat3ch commented Apr 2, 2022

Hi @hadley,
Sorry about the missing reprex. Here's a reprex of one of the ideas - to define a function elsewhere (since it might be quite large) and inherit the params/description when it's made a method of an R6 class:

# A function defined elsewhere

#' This function Would be great as an R6 method if it's docs were inherited
#' @param x Is this possible?

thefun <- function(x) {
  x + 1
}

#' R6Class that doessn't currently allow inheriting documentation
theR6 <- R6::R6Class(classname = "demo",
            public = list(
              #' @inherit thefun params description
              thefun = thefun
            ))

Just throw the code above in a package and document it. The errors should look something like:
image
I'll see about reprexing the other ideas momentarily.

@yogat3ch
Copy link
Author

yogat3ch commented Apr 2, 2022

The second idea is to allow defining of R6 Methods dynamically. The case below is an example where methods might be dynamically generated to load specific files from disk:

list_of_files <- rlang::set_names(paste0(letters, ".csv"), letters)
#' R6Class that doessn't currently allow dynamic method definitions
theR6 <- R6::R6Class(classname = "demo",
            public = rlang::list2(
              !!!purrr::map(list_of_files, ~rlang::new_function(args = rlang::pairlist2(file = .x), body = rlang::expr(read.csv(file))))
            ))

This now produces an error when documenting that looks like this:
image
(It's more instructive now than it was when I previously tried this. I haven't tried what's suggested in the error yet.)

sessionInfo R version 4.1.0 (2021-05-18) Platform: x86_64-w64-mingw32/x64 (64-bit) Running under: Windows 10 x64 (build 19044)

Matrix products: default

locale:
[1] LC_COLLATE=English_United States.1252
[2] LC_CTYPE=English_United States.1252
[3] LC_MONETARY=English_United States.1252
[4] LC_NUMERIC=C
[5] LC_TIME=English_United States.1252

attached base packages:
[1] stats graphics grDevices utils datasets methods
[7] base

other attached packages:
[1] maleta_0.0.0.9000

loaded via a namespace (and not attached):
[1] pillar_1.7.0 compiler_4.1.0 remotes_2.4.2
[4] prettyunits_1.1.1 tools_4.1.0 digest_0.6.29
[7] testthat_3.0.4.9000 pkgbuild_1.2.1 pkgload_1.2.4
[10] memoise_2.0.1 lifecycle_1.0.1 tibble_3.1.6
[13] UU_0.0.0.9003 pkgconfig_2.0.3 rlang_1.0.1
[16] rstudioapi_0.13 cli_3.1.1 DBI_1.1.1
[19] commonmark_1.7 xfun_0.29 fastmap_1.1.0
[22] xml2_1.3.3 knitr_1.37 roxygen2_7.1.2
[25] withr_2.4.3 dplyr_1.0.8 httr_1.4.2
[28] stringr_1.4.0 generics_0.1.2 desc_1.4.0
[31] fs_1.5.2 vctrs_0.3.8 devtools_2.4.3.9000
[34] rprojroot_2.0.2 tidyselect_1.1.2 glue_1.6.0
[37] R6_2.5.1.9000 processx_3.5.2 fansi_1.0.2
[40] sessioninfo_1.2.2 rdrop2_0.8.2.1 purrr_0.3.4
[43] callr_3.7.0 magrittr_2.0.1 usethis_2.1.3
[46] ps_1.6.0 ellipsis_0.3.2 assertthat_0.2.1
[49] utf8_1.2.2 stringi_1.7.6 cachem_1.0.6
[52] crayon_1.5.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature a feature request or enhancement R6 6️⃣ reprex needs a minimal reproducible example
Projects
None yet
Development

No branches or pull requests

3 participants