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

Active bindings are being triggered by accessing the encapsulating environment #288

Open
mattwarkentin opened this issue Jul 31, 2024 · 0 comments

Comments

@mattwarkentin
Copy link

mattwarkentin commented Jul 31, 2024

Hi,

I am really not sure if this is an R6 issues or an issue with my approach. I am definitely pushing my limits of meta-programming in R. The actual use-case that causes this issue is very convoluted so I have tried to boil down the issue in some pseudocode below.

The challenge is that I want to create active bindings in my R6 object, but I want them to live in their own environment, rather than the top-level of the R6 instance so users can access them via object$Env$binding instead of object$binding.

I am using active bindings because the tables are being pulled in real time from an API. Accessing the active binding calls a function that pulls it from the API. In order to create an active binding for EVERY table at the time of initializing the R6 instance, I am using some potentially off-brand meta-programming. The code "works" in that the active bindings are created and they run correctly to pull in the tables. The issue is that simply accessing object$Env triggers every active binding in Env. This is not as desired and prohibitively slow as it pulls hundreds of large tables from an API.

Any idea why this is happening?

library(R6)

Foo <- R6Class(
  classname = 'Foo',
  public = list(
    initialize = function() {
      private$load_table_bindings()
    },
    get_table_from_api = function(name) {
      # << Code to pull table `name` from API >>
    },
    Tables = NULL
  ),
  private = list(
    table_names = c(#<< character vector of table names not known until object is created >>),
    load_table_bindings = function() {
      self$Tables <- rlang::env()
      purrr::walk(private$table_names, \(name) {
        f <- function() {
          self$get_table_from_api(name)
        }
        rlang::env_bind_active(self$Tables, '{name}' := f)
      })
    }
  )
)

foo <- Foo$new()

# Triggers every active binding in `Tables` environment
foo$Tables
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant