rr6

What is the best way to combine elements from R6 into a tibble?


I am learning R6 and plan to use it in the Shiny app I am developing. My goal is to separate business logic from the app interface and reuse it across different modules and sub-modules, as suggested in the book Engineering Production-Grade Shiny Apps.

My current approach is as follows:

library(R6)
library(tibble)

Stack_Overflow <- R6Class(
  classname = "Stack_Overflow_example",
  
  public = list(
    vec1 = c(1, 2, 3),
    vec2 = c(4, 5, 6),
    vec3 = c(7, 8, 9),
    
    form_tibble = \() {
      tibble(
        vec_1 = self$vec1,
        vec_2 = self$vec2,
        vec_3 = self$vec3
      )
    }
  )
)

When I call form_tibble(), I get the expected tibble:

example <- Stack_Overflow$new()
example$form_tibble()

> example$form_tibble()
# A tibble: 3 × 3
  vec_1 vec_2 vec_3
  <dbl> <dbl> <dbl>
1     1     4     7
2     2     5     8
3     3     6     9

However, I'd like to apply this technique to my real project, in which an R6 class object may contain more than 30 variables, assuming they have the same length. While I could copy and paste to form the tibble structure like the example above, my understanding of R suggests that this should be possible to generate dynamically—I’m just not sure how to implement it in R6.

Given this context, I have two questions:

  1. Is this the best approach?
  2. Is there a way to create the tibble more dynamically?

Solution

  • Convert to a list using as.list.R6(), remove elements that are environments or functions, then coerce to a tibble:

    library(R6)
    library(tibble)
    
    Stack_Overflow <- R6Class(
      classname = "Stack_Overflow_example",
      public = list(
        vec1 = c(1, 2, 3),
        vec2 = c(4, 5, 6),
        vec3 = c(7, 8, 9),
        form_tibble = \() {
          self_l <- as.list(self)
          self_l <- self_l[!(sapply(self_l, typeof) %in% c("environment", "closure"))]
          # for some reason the list elements are in reverse order - so use `rev()`
          as_tibble(rev(self_l))
        }
      )
    )
    
    example <- Stack_Overflow$new()
    example$form_tibble()
    # # A tibble: 3 × 3
    #    vec1  vec2  vec3
    #   <dbl> <dbl> <dbl>
    # 1     1     4     7
    # 2     2     5     8
    # 3     3     6     9
    

    Depending on what your actual object looks like, you may have to modify to filter out other object types or based on other conditions.