Search code examples
rr6

define a bracket (`[`) operator on an R6 class


Here's what does not work:

library(R6)

Foo = R6::R6Class(
    'Foo',
    public = list(
        X = NULL,
        metadata = NULL,
        initialize = function(X, metadata){
            self$X = X
            self$metadata = metadata
        },
        `[` = function(selection){
            subfoo = Foo$new(X = X[selection], 
                             metadata = self$metadata)
            return(subfoo)
        }
    )
)

Specifically, the [ method is garbage:

> X = matrix(1:8, ncol = 2)
> foo = Foo$new(X, 'blah blah')
> foo[1:2,]
Error in foo[1:2, ] : object of type 'environment' is not subsettable

The desired result is that foo[1:2,] would be an object of class Foo just like foo except that its matrix foo$X is smaller. Is there a direct way to implement this that exposes the [ operator directly to the user?


Solution

  • An answer is better late than never I suppose. The problem is that you are registering methods that can be called like

    x$`[`(1:3)
    

    whereas you want

    x[1:3]
    

    The following will dispatch all [ and [<- calls (via S3) correctly for all R6 objects.

    `[.R6` <- function(x, ...) x$`[`(...) 
    `[<-.R6` <- function(x, ...) x$`[<-`(...) 
    

    Note that you shouldn't do anything like this for the [[ methods, as these are already defined and used because R6 objects are environments.

    Ideally it would be great if ( could also be overridden so that we could create functor objects (e.g. calling x(2)), but I don't know how this could be done..