R6 private fields with `<-` and `$` access

I want to create an R6 object that can accept only pre-defined fields. I can do this by defining get and set methods. However, to apply this to my existing code I'd like to extend syntax to replace get with $ and set with <-. Since I know very little about R6, I asked ChatGPT, and got this answer:

state_container <- R6Class(
  "state_container",
  public = list(
    initialize = function(fields) {
      private$fields <- fields
      private$values <- list()
    },

    get = function(field) {
      if (!field %in% private$fields) {
        stop(sprintf("Field '%s' is not a predefined field.", field))
      }
      private$values[[field]]
    },

    set = function(field, value) {
      if (!field %in% private$fields) {
        stop(sprintf("Field '%s' is not a predefined field.", field))
      }
      private$values[[field]] <- value
    },

    get_all = function() {
      lapply(private$fields, function(field) private$values[[field]])
    },

    # Define method to support app_state$field syntax for getting
    `$.get` = function(field) {
      self$get(field)
    },

    # Define method to support app_state$field <- value syntax for setting
    `$<-.set` = function(field, value) {
      self$set(field, value)
    }
  ),

  private = list(
    fields = NULL,
    values = NULL
  )
)

This seems to work well with set and get:

> state <- state_container$new(c("foo", "bar"))
> state$set("foo", "one")
> state$get("foo")
[1] "one"
> state$set("not_allowed", "two")
Error in state$set("not_allowed", "two") : 
  Field 'not_allowed' is not a predefined field.
> state$get("not_allowed")
Error in state$get("not_allowed") : 
  Field 'not_allowed' is not a predefined field.

However, the proposed syntax extension does not work:

> state$foo <- "one"
Error in state$foo <- "one" : cannot add bindings to a locked environment
> state$foo
NULL
> state$not_allowed
NULL

What I need is for state$foo <- "one" to work and be aware of not predefined fields, and for state$foo to return the correct value and for state$not_allowed to throw an error.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.