r - S3(在R中)中单个重载运算符的多次调度
问题描述
在使用 S3 类时,我想重载 R 中的“*”(乘法运算符)。
我看到 * 在系统中已经是通用的,但我也想要它“generic2”,即在第二个参数上调度。
用例如下:假设我的类名为“Struct”。我希望能够允许所有这三种情况
Struct * Struct
Struct * Number
Number * Struct
但是我发现,如果我允许在第二个参数上进行调度,则(已经存在的)第一个参数上的调度将被覆盖!
有没有办法可以在 S3 中做到这一点?
# "generic1" already exists for '*'
'*' <- function(x,y){
UseMethod('*2',y)
}
'*.Struct'<-function(x,y){
# must both be structs, so dispatch 'normally' if not
"times(1)"
}
`*2.Struct`<-function(x,y){
# must both be structs, so dispatch 'normally' if not
"times(2)"
}
给我...
> struct1 * struct2
[1] "times(2)"
> 2 * struct2
[1] "times(2)"
> struct1 * 2
Error in UseMethod("*2", y) :
no applicable method for '*2' applied to an object of class "c('double', 'numeric')"
>
如果我使用这个,而不是
'*' <- function(x,y){ UseMethod('*',x)}
然后第一个参数的调度起作用,相反的情况发生了:
> struct1 * 2
[1] "times(1)"
> struct1 * struct2
[1] "times(1)"
> 2* struct1
Error in UseMethod("*", x) :
no applicable method for '*' applied to an object of class "c('double', 'numeric')"
>
所以看起来他们肯定会互相覆盖。
关于两者如何和平和富有成效地共存的任何想法?
解决方案
您可以检查函数内部:
'*.Struct'<-function(x,y){
if(inherits(x,'Struct') && inherits(y,'Struct'))
"Struct*Struct"
else if(inherits(y,'Struct'))
"N*Struct"
else
"Struct*N"
}
# N.B.: you don't need to redefine `*`,`*2.Struct` etc
例如:
struct1=structure(5,class='Struct')
struct2=structure(3,class='Struct')
struct1*struct2
# [1] "Struct*Struct"
struct1*2
# [1] "Struct*N"
3*struct2
# [1] "N*Struct"
如此处所述,使用以下规则对两个参数进行调度:
如果只为一个参数找到一个方法,或者为两个参数找到相同的方法,则使用它。如果找到不同的方法,则会出现关于“不兼容方法”的警告:在这种情况下,或者如果没有为任一参数找到方法,则使用内部方法。
因此,例如,由于还有一个*.difftime
方法定义,这些情况会给出带有警告的奇怪结果:
difftimeObj <- Sys.time()-Sys.time()
struct1*difftimeObj
# [1] 0
# attr(,"units")
# [1] "secs"
# attr(,"class")
# [1] "Struct"
# Warning message:
# Incompatible methods ("*.Struct", "*.difftime") for "*"
difftimeObj*struct2
# Time difference of 0 secs
# Warning message:
# Incompatible methods ("*.difftime", "*.Struct") for "*"
而这些代替工作:
struct1*unclass(difftimeObj)
# [1] "Struct*N"
unclass(difftimeObj)*struct2
# [1] "N*Struct"
# skipping dispatching
`*.Struct`(struct1, difftimeObj)
# [1] "Struct*N"
`*.Struct`(difftimeObj, struct2)
# [1] "N*Struct"
推荐阅读
- reactjs - React-Jest:axios.get.mockRejectedValue 不尊重异步等待
- javascript - 如何为嵌套数组中的元素生成索引链?
- three.js - 与相机平行的边界框
- distribution - 使用 Scilab 进行帕累托分布参数估计,为什么我会得到这么大的值?
- docker - Kubernetes 中 Minio 支持的 Docker Registry 使用 Minio 的自签名证书 - x509 错误
- javascript - 创建pdf并将其转换为base64
- tensorflow.js - 如何在 tensorflow.js 上加载 onnx 模型?
- python - TypeError:_save_dispatcher() 得到了一个意外的关键字参数“fmt”
- jaxb - 接口的@XmlIDREF
- python - 如何找到一个源和所有剩余顶点之间的最短路径?