3

我试图将@R 中的运算符变成 S3 系统的通用函数。

基于编写 R 扩展中的章节:添加新的泛型我尝试像这样实现泛型@

`@` <- function(object, name) UseMethod("@")
`@.default` <- function(object, name) base::`@`(object, name)

但是,这似乎不起作用,因为它破坏@了 S4 方法。我使用Matrix包作为 S4 实例的示例:

Matrix::Matrix(1:4, nrow=2, ncol=2)@Dim

(Matrix::Matrix(1:4, nrow @.default= 2, ncol = 2), Dim) 中的错误:“dgeMatrix”类的这个对象没有名称“name”的插槽

如何实现泛型@以便在 S4 类的情况下正确调度?


编辑

还对为什么它可能不是一个好主意的意见感兴趣?

4

1 回答 1

3

@R 的文档对于是否已经是通用的有点混乱:帮助页面@说它是,但它没有在internalGenerics页面上列出。

运算符具有特定的@行为以及(也许)是通用的。来自帮助页面@:“已检查对象是 S4 对象(请参阅 isS4),尝试在任何其他对象上使用 @ 是错误的。” 这似乎排除了为 S3 类编写方法的可能性,尽管文档不清楚此检查是在方法分派之前(如果有的话)还是之后(如果您为某些 S3 类提供特定方法,则可以跳过)。

@您可以按照评论中的建议通过完全重新定义什么来实现您想要的:

`@.default` <- function(e1,e2) slot(e1,substitute(e2))

但有两个理由不这样做:

1)一旦有人加载你的包,它就会取代正常的@功能,所以如果人们用其他 S4 对象调用它,他们会得到你的版本而不是 R 基础版本。

2)这个版本比内部版本效率低得多,因为(1)你只是强迫你的用户使用它(除非他们使用繁琐的结构base::"@"(e1,e2))。效率可能与您的用例无关,但可能对您的用户使用 S4 的其他代码很重要。

实际上,一个合理的折衷方案可能是定义您自己的二元运算符%@%,并使用默认方法调用@。那是,

`%@%` <- function(e1,e2) slot(e1,substitute(e2))
setGeneric("%@%")

这在实践中被称为如下:

> setClass("testClass",slots=c(a="character")) -> testClass
> x <- testClass(a="cheese")
> x %@% a
[1] "cheese"
于 2018-09-14T08:37:25.963 回答