在 R6 class 上定义括号 (`[`) 运算符
define a bracket (`[`) operator on an R6 class
以下是无效的:
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,]
将是 class Foo
的对象,就像 foo
一样,只是它的矩阵 foo$X
更小。是否有直接的方法来实现此操作,将 [
运算符直接暴露给用户?
我想迟到总比不到好。问题是您正在注册可以像
这样调用的方法
x$`[`(1:3)
而你想要
x[1:3]
以下将为所有 R6 对象正确分派所有 [
和 [<-
调用(通过 S3)。
`[.R6` <- function(x, ...) x$`[`(...)
`[<-.R6` <- function(x, ...) x$`[<-`(...)
请注意,您不应该为 [[
方法做任何类似的事情,因为这些方法已经被定义和使用,因为 R6 对象是环境。
理想情况下,如果 (
也可以被覆盖,这样我们就可以创建仿函数对象(例如调用 x(2)
),但我不知道如何做到这一点。
如果其他人也在寻找它,这里有一个完整的工作示例(基于 ):
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 package (v0.3.0)
于 2020-10-09 创建
(如果需要,return 值可以是另一个 Foo 对象。为了简单起见,我正在 return 使用向量)
以下是无效的:
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,]
将是 class Foo
的对象,就像 foo
一样,只是它的矩阵 foo$X
更小。是否有直接的方法来实现此操作,将 [
运算符直接暴露给用户?
我想迟到总比不到好。问题是您正在注册可以像
这样调用的方法x$`[`(1:3)
而你想要
x[1:3]
以下将为所有 R6 对象正确分派所有 [
和 [<-
调用(通过 S3)。
`[.R6` <- function(x, ...) x$`[`(...)
`[<-.R6` <- function(x, ...) x$`[<-`(...)
请注意,您不应该为 [[
方法做任何类似的事情,因为这些方法已经被定义和使用,因为 R6 对象是环境。
理想情况下,如果 (
也可以被覆盖,这样我们就可以创建仿函数对象(例如调用 x(2)
),但我不知道如何做到这一点。
如果其他人也在寻找它,这里有一个完整的工作示例(基于
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 package (v0.3.0)
于 2020-10-09 创建(如果需要,return 值可以是另一个 Foo 对象。为了简单起见,我正在 return 使用向量)