2

I am developing an R package and use R6 internally. I have two R6 objects:

  1. A Foo object which contains lots of data and methods of summarize the whole data;
  2. A Bar object which contains subsetting methods of Foo's data and methods of query that specific subseted data.

What I want to do is to create a clone of the Bar R6Class Generator object and pass an environment which contains all the data of the Foo object. I could not find a way to complete clone an R6Class Generator.

NOTE: I do not want to directly split the data in Foo and pass that data to Bar$new, which will will dramatically slow down the whole process as lots of Bar objects will be created rather than the only desired one.

Below is a simple example:

library(R6)

Foo <- R6Class(classname = "Foo",
    public = list(
        initialize = function (x) {
            private$m_x <- x
            private$m_bar_gen <- private$create_bar_gen(Bar)
        },

        new_bar = function () {
            private$m_bar_gen$new()
        }),

    private = list(
        m_x = NULL,
        m_bar_gen = NULL,

        create_bar_gen = function (Bar) {
            my_bar <- list2env(as.list.environment(Bar), parent = emptyenv())
            class(my_bar) <- "R6Generator"
            my_bar$self <- my_bar
            my_bar$set("private", "m_x", private$m_x, overwrite = TRUE)
            my_bar
        }
    )
)

Bar <- R6Class(classname = "Bar",
    public = list(
        initialize = function () {
            stopifnot(!is.null(private$m_x))
            private$m_x
        }
    ),
    private = list(
        m_x = NULL
    )
)

This will stop as private$m_x is not defined

Bar$new()
#> Error: !is.null(private$m_x) is not TRUE

After a Foo object is initialized,

(foo_1 <- Foo$new(1))
#> <Foo>
#>   Public:
#>     clone: function (deep = FALSE) 
#>     initialize: function (x) 
#>     new_bar: function () 
#>   Private:
#>     create_bar_gen: function (Bar) 
#>     m_bar_gen: R6Generator
#>     m_x: 1

this will work

foo_1$new_bar()
#> <Bar>
#>   Public:
#>     clone: function (deep = FALSE) 
#>     initialize: function () 
#>   Private:
#>     m_x: 1

but the original Bar R6Class Generator has been changed as well

Bar$private_fields$m_x
#> [1] 1

It seems that the private$create_bar_gen() could not complete copy an R6Class Generator. my_bar$set will both set the original and the new one.

(foo_2 <- Foo$new(2))
#> <Foo>
#>   Public:
#>     clone: function (deep = FALSE) 
#>     initialize: function (x) 
#>     new_bar: function () 
#>   Private:
#>     create_bar_gen: function (Bar) 
#>     m_bar_gen: R6Generator
#>     m_x: 2

foo_2$new_bar()
#> <Bar>
#>   Public:
#>     clone: function (deep = FALSE) 
#>     initialize: function () 
#>   Private:
#>     m_x: 2

Bar$private_fields$m_x
#> [1] 2

foo_1$new_bar()
#> <Bar>
#>   Public:
#>     clone: function (deep = FALSE) 
#>     initialize: function () 
#>   Private:
#>     m_x: 2

0 Answers0