Определить оператор скобки (`[`) в классе R6
Вот что не работает:
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
как foo
кроме того, что его матрица foo$X
меньше Есть ли прямой способ реализации этого, который подвергает [
оператор напрямую к пользователю?
1 ответ
Ответ лучше поздно, чем никогда, я полагаю. Проблема в том, что вы регистрируете методы, которые могут быть вызваны как
x$`[`(1:3)
тогда как ты хочешь
x[1:3]
Следующее будет отправлять все [
а также [<-
звонки (через S3) правильно для всех объектов R6.
`[.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
Создано 2020-10-09 пакетом REPEX (v0.3.0)
(Возвращаемое значение может быть другим объектом Foo, если вам это нужно. Я возвращаю вектор для простоты)