5

这是不起作用的:

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)
        }
    )
)

具体来说,该[方法是垃圾:

> 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

期望的结果是,除了它的矩阵更小之外,这foo[1:2,]将是一个类的对象Foo。有没有直接的方法来实现这一点,将操作员直接暴露给用户?foofoo$X[

4

2 回答 2

5

我想迟到总比没有好。问题是您正在注册可以调用的方法

x$`[`(1:3)

而你想要

x[1:3]

以下将为所有 R6 对象正确调度所有[和调用(通过 S3)。[<-

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

请注意,您不应该对这些方法执行任何此类[[操作,因为这些方法已经定义和使用,因为 R6 对象是环境。

理想情况下,如果(也可以被覆盖,这样我们就可以创建仿函数对象(例如调用x(2)),那将是很棒的,但我不知道如何做到这一点..

于 2018-08-28T21:15:31.607 回答
1

如果其他人也在寻找它,这是一个完整的工作示例,说明如何执行此操作(基于Ian Fellows 的回答):

library(R6)

Foo = R6::R6Class(
  'Foo',
  public = list(
    x = NULL,
    initialize = function(x) {
      self$x = x
    },
    
    `[` = function(idx) {
      self$x[idx]
    },
    
    `[<-` = function(idx, value) {
      self$x[idx] <- value
      invisible(self)  # important!
    },
    
    length = function() {
      length(self$x)
    }
  )
)

# set up method dispatch
`[.Foo`    <- function(obj, ...) obj$`[`(...) 
`[<-.Foo`  <- function(obj, ...) obj$`[<-`(...) 
length.Foo <- function(obj, ...) obj$length(...)

# test
foo <- Foo$new(c(1,2,3))
(n <- length(foo))
#> [1] 3
foo[1:n]
#> [1] 1 2 3
foo[2] <- 0
foo[1:n]
#> [1] 1 0 3

reprex 包(v0.3.0)于 2020 年 10 月 9 日创建

(如果需要,返回值可以是另一个 Foo 对象。为简单起见,我返回一个向量)

于 2020-10-09T13:03:50.253 回答