实现提取并为 S3 类分配运算符的最佳方法



假设我有一个类似列表foo类的对象,我想为它实现分配运算符。该类与普通列表的不同之处在于每个元素都以"bar_"前缀命名(这只是一个虚构的示例(。所以我对分配运算符的天真实现将是:

"[<-.foo" <- function(x, i, value) {
x[paste0("bar_", i)] <- value
}

显然,这是行不通的,因为它进入无限循环:

as.foo <- function(x) {
names(x) <- paste0("bar_", names(x))
class(x) <- c(class(x), "foo")
x
}
x <- as.foo(list(a = 1, b = 2))
x["a"] <- 42
## Error: C stack usage  7970836 is too close to the limit

实施这种方法的最佳做法是什么?

子集/子赋值函数很特殊,因为在 R 级别没有泛型方法,也没有默认方法。这一切都在 C 代码中处理。原因当然是性能:S3 方法调度相对较慢,子集需要尽可能快,因为它被使用得太多了。

我会暂时删除该类:

"[<-.foo" <- function(x, i, value) {
theclass <- class(x)
class(x) <- class(x)[-inherits(x, "foo", TRUE)]
x[paste0("bar_", i)] <- value
class(x) <- theclass
x
}

顺便说一句,我会重写as.foo

as.foo <- function(x) {
stopifnot(is.list(x))
names(x) <- paste0("bar_", names(x))
class(x) <- c("foo", attr(x, "class"))
x
}

这样可以避免将隐式类添加到类属性。

相关内容

  • 没有找到相关文章

最新更新